You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

422 lines
15 KiB

2 months ago
package marketwsscliert
import (
"fmt"
"github.com/shopspring/decimal"
"math/rand"
"strconv"
"strings"
"sync"
"time"
"wss-pool/cmd/common"
"wss-pool/config"
"wss-pool/internal/data"
"wss-pool/internal/model"
"wss-pool/logging/applogger"
models "wss-pool/pkg/model"
)
var (
conversion_forex = decimal.RequireFromString("1")
proportion_forex = decimal.RequireFromString("1000000")
)
var (
muForex = sync.Mutex{}
ModifyForexMap = make(map[string]ModifyForex)
)
type ModifyForex struct {
ForexCode string `json:"ForexCode"` // 外汇
BeginTime string `json:"BeginTime"` // 开始时间-date
EndTime string `json:"EndTime"` // 结束时间-date
Price decimal.Decimal `json:"Prices"` // 设置价格
ChangePrice decimal.Decimal `json:"ChangePrice"` // 插针变化价格(开盘价,初始浮点变化区间起始价) - (初始浮点变化区间结束价-动态直至不在变化) - (浮点变化区间结束后的起始价格)
EndPrice decimal.Decimal `json:"EndPrice"` // 浮点变化区间结束后的结束价格
Proportion decimal.Decimal `json:"Proportion"` // 浮动率
CheckBool bool `json:"CheckBool"` // 判断是负增长还是正增长
Digits int `json:"Digits"` // 保留几位小数
Step int `json:"Step"` // 浮点数
BeginUnix int64 `json:"BeginUnix"` // 开始时间-unix
EndUnix int64 `json:"EndUnix"` // 结算时间-unix
RestoreChangePrice decimal.Decimal `json:"RestorePrice"` // 插针恢复变化价格(开盘价,初始浮点变化区间起始价) - (初始浮点变化区间结束价-动态直至不在变化) - (浮点变化区间结束后的起始价格)
RestoreBeginTime string `json:"RestoreBeginTime"` // 插针恢复开始时间-date
RestoreEndTime string `json:"RestoreEndTime"` // 插针恢复结束时间-date
RestoreBeginUnix int64 `json:"RestoreBeginUnix"` // 插针恢复开始时间-unix
RestoreEndUnix int64 `json:"RestoreEndUnix"` // 插针恢复结束时间-unix
RestoreBool bool `json:"RestoreBool"` // 插针恢复
RestoreSetChangePrice bool `json:"RestoreSetChangePrice"` // 插针恢复更新
DataHandling map[int]string `json:"DataHandling"` // 数据处理-需要初始化
NumIntervals int `json:"NumIntervals"` // 数据处理-间隔次数
}
func SetValue_Forex(key string, value ModifyForex) {
muForex.Lock()
defer muForex.Unlock()
ModifyForexMap[key] = value
}
func GetValue_Forex(key string) (ModifyForex, bool) {
muForex.Lock()
defer muForex.Unlock()
value, ok := ModifyForexMap[key]
return value, ok
}
func getData_Forex() []model.ForexMarket {
forex := model.NewForexMarket()
result := forex.ListModifyForex()
return result
}
// 外汇加载交易对插针列表
func GetModifyForex() {
data.InitGorm(config.Config.Bourse)
for {
t := time.NewTimer(10 * time.Second)
<-t.C
result := getData_Forex()
applogger.Debug("加载需要插针的交易对设置:%v", result)
for _, v := range result {
end, _ := common.TimeStrToTimes(v.EndTime)
if end.Unix() < time.Now().Unix() {
applogger.Error("该调价已过期......")
delete(ModifyForexMap, v.TradeName)
forex := model.NewForexMarket()
forex.ID = v.ID
forex.UpdateIsGetOne()
continue
}
price, err := decimal.NewFromString(v.MaxPrice)
if price.IsZero() {
applogger.Error("price err:%v", price)
continue
}
// 插针设置
begin, err := common.TimeStrToTimestamp(v.BeginTime)
if err != nil {
applogger.Error("begin err:%v", err)
continue
}
ends, err := common.TimeStrToTimestamp(v.EndTime)
if err != nil {
applogger.Info("end err:%v", err)
continue
}
// 插针恢复
restoreBegin, err := common.TimeStrAddFiveTime(v.BeginTime)
if err != nil {
applogger.Error("restoreBegin err:%v", err)
continue
}
restoreEnds, err := common.TimeStrAddFiveTime(v.EndTime)
if err != nil {
applogger.Info("restoreEnds err:%v", err)
continue
}
restoreBeginUnix, err := common.TimeStrToTimestamp(restoreBegin)
if err != nil {
applogger.Error("restoreBeginUnix err:%v", err)
continue
}
restoreEndsUnix, err := common.TimeStrToTimestamp(restoreEnds)
if err != nil {
applogger.Error("restoreEndsUnix err:%v", err)
continue
}
//判断当前外汇,是否有任务还在执行
if mapVal, ok := GetValue_Forex(v.TradeName); ok {
if mapVal.EndUnix >= time.Now().Unix() {
applogger.Info(v.TradeName, " is run")
continue
}
}
// 第二次浮点随机数值的端点值(结束浮点)
proportion_value := conversion_forex.Add(decimal.NewFromInt32(int32(v.Step)).Div(proportion_forex))
// 写入缓存中
SetValue_Forex(v.TradeName, ModifyForex{
ForexCode: v.TradeName,
BeginTime: v.BeginTime, // 设置开始时间
EndTime: v.EndTime, // 设置结束时间
Price: price, // 设置价格
ChangePrice: decimal.Zero, // 插针变化价格(开盘价,初始浮点变化区间起始价) - (初始浮点变化区间结束价-动态直至不在变化) - (浮点变化区间结束后的起始价格)
EndPrice: decimal.Zero, // 浮点变化区间结束后的结束价格
Proportion: proportion_value, // 区间浮动率
CheckBool: false,
Digits: v.KeepDecimal,
Step: v.Step,
BeginUnix: begin, // 插针开始时间
EndUnix: ends, // 插针结束时间
RestoreBeginTime: restoreBegin, // 插针恢复开始时间-date
RestoreEndTime: restoreEnds, // 插针恢复结束时间-date
RestoreBeginUnix: restoreBeginUnix, // 插针恢复开始时间-unix
RestoreEndUnix: restoreEndsUnix, // 插针恢复结束时间-unix
RestoreBool: false, // 插针恢复标识
RestoreSetChangePrice: false, // 插针恢复更新
RestoreChangePrice: decimal.Zero, // 插针恢复变化价格(开盘价,初始浮点变化区间起始价) - (初始浮点变化区间结束价-动态直至不在变化) - (浮点变化区间结束后的起始价格)
DataHandling: make(map[int]string),
NumIntervals: 5,
})
forex := model.NewForexMarket()
forex.ID = v.ID
forex.UpdateIsGetOne()
}
}
}
// 外汇插针
func RunModifyForex(param models.ForexJsonData) (models.ForexJsonData, bool) {
// 缓存中插针的交易对信息
val, ok := GetValue_Forex(param.Pair)
if !ok {
return param, false
}
// 不在设置的时间区间范围过滤
if val.BeginUnix > param.Timestamp || val.EndUnix < param.Timestamp {
return param, false
}
applogger.Debug("交易对%v,原始数据:%v", param.Pair, param)
// 数据赋值
changePrice_New := val.ChangePrice
price_new := val.Price
endPrice_new := val.EndPrice
checkBool := val.CheckBool
// 第一次浮点区间的起始价
if val.ChangePrice.IsZero() {
changePrice_New = decimal.NewFromFloat(param.Close) // k线闭盘价(即浮点起始价)
endPrice_new = price_new.Mul(val.Proportion) // 第二次浮点结束价
if changePrice_New.Cmp(price_new) >= 1 {
checkBool = true
}
}
// 平滑价格生成(价格趋向结束价)
var price decimal.Decimal
if checkBool {
// 负增长
if changePrice_New.Cmp(price_new) >= 0 {
changePrice_New = changePrice_New.Div(val.Proportion)
price = changePrice_New
// 更新缓存变量字段
val.ChangePrice = changePrice_New
val.Price = price_new
val.EndPrice = endPrice_new
val.CheckBool = checkBool
SetValue_Forex(val.ForexCode, val)
} else {
randomPrice := RandomBetween(price_new.Div(val.Proportion).InexactFloat64(), endPrice_new.InexactFloat64())
price = decimal.NewFromFloat(randomPrice)
}
} else {
// 正增长
if changePrice_New.Cmp(price_new) <= 0 {
changePrice_New = changePrice_New.Mul(val.Proportion)
price = changePrice_New
// 更新缓存变量字段
val.ChangePrice = changePrice_New
val.Price = price_new
val.EndPrice = endPrice_new
val.CheckBool = checkBool
SetValue_Forex(val.ForexCode, val)
} else {
randomPrice := RandomBetween(changePrice_New.Div(val.Proportion).InexactFloat64(), endPrice_new.InexactFloat64())
price = decimal.NewFromFloat(randomPrice)
}
}
param.Open = changePrice_New.InexactFloat64()
param.Close = price.InexactFloat64()
if price.GreaterThan(decimal.NewFromFloat(param.High)) {
param.High = price.InexactFloat64()
}
if price.LessThan(decimal.NewFromFloat(param.Low)) {
param.Low = price.InexactFloat64()
}
forexJson := models.ForexJsonData{
Event: "CAS",
Pair: param.Pair,
Open: param.Open,
Close: param.Close,
High: param.High,
Low: param.Low,
Volume: param.Volume,
Timestamp: param.Timestamp,
}
applogger.Debug("交易对%v,插针数据:%v", param.Pair, forexJson)
return forexJson, true
}
func RunModifyForexNew(param models.ForexJsonData) (models.ForexJsonData, bool) {
// 缓存中插针的交易对信息
val, ok := GetValue_Forex(param.Pair)
if !ok {
return param, false
}
// 不在设置的时间区间范围过滤
if val.BeginUnix > param.Timestamp || val.EndUnix < param.Timestamp {
if val.RestoreBeginUnix > param.Timestamp || val.RestoreEndUnix < param.Timestamp || val.RestoreBool {
return param, false
} else {
applogger.Debug("恢复交易对%v,原始数据:%v", param.Pair, param)
if val.RestoreChangePrice.IsZero() {
var startT, endT time.Time
var startF, endF float64
startT = common.TimeStringToTime(val.RestoreBeginTime) // 设置插针开始时间
endT = common.TimeStringToTime(val.RestoreEndTime) // 设置插针结束时间
msgTime := DivideTimeInterval(startT, endT, val.NumIntervals) // 时间区间划分
// 判定插针结束价格和当前即时价格
if param.Close == val.ChangePrice.InexactFloat64() {
val.RestoreBool = true
SetValue_Forex(val.ForexCode, val)
return param, false
} else {
startF = val.ChangePrice.InexactFloat64() // 插针结束价格
endF = param.Close // 恢复即时价格
}
applogger.Debug("开始价格:%v,结束价格:%v", startF, endF)
msgFloat := DivideFloatInterval(startF, endF, val.NumIntervals) // 浮点区间划分
var msgTF = make(map[int]string)
for i, mt := range msgTime {
mf, okM := msgFloat[i]
if okM {
msgTF[i] = fmt.Sprintf("%v,%v", mt, mf)
applogger.Debug("msgTF:%v,%v", i, msgTF[i])
}
}
val.DataHandling = msgTF
val.RestoreSetChangePrice = true
}
}
} else {
applogger.Debug("插针交易对%v,原始数据:%v", param.Pair, param)
// 第一次浮点区间的起始价
if val.ChangePrice.IsZero() {
var startT, endT time.Time
var startF, endF float64
val.ChangePrice = decimal.NewFromFloat(param.Close) // k线闭盘价(即浮点起始价)
startT = common.TimeStringToTime(val.BeginTime) // 设置插针开始时间
endT = common.TimeStringToTime(val.EndTime) // 设置插针结束时间
msgTime := DivideTimeInterval(startT, endT, val.NumIntervals) // 时间区间划分
startF = param.Close // 设置插针开始价格
endF = val.Price.InexactFloat64() // 设置插针结束价格
applogger.Debug("开始价格:%v,结束价格:%v", startF, endF)
msgFloat := DivideFloatInterval(startF, endF, val.NumIntervals) // 浮点区间划分
var msgTF = make(map[int]string)
for i, mt := range msgTime {
mf, okM := msgFloat[i]
if okM {
msgTF[i] = fmt.Sprintf("%v,%v", mt, mf)
applogger.Debug("msgTF:%v,%v", i, msgTF[i])
}
}
val.DataHandling = msgTF
}
}
/* 浮点区间价格随机生成浮点值
1判定当前时间戳在区间内
2在区间内则生成对应的浮点值
*/
var price decimal.Decimal
for _, msg := range val.DataHandling {
// msgTF:0,1734426000-1734426108,2652.33-2653.5299999999997
splitMsg := strings.Split(msg, ",")
if len(splitMsg) >= 2 {
splitT := strings.Split(splitMsg[0], "-") // 开始时间~结束时间 1734426000-1734426108
if len(splitT) >= 2 {
start, _ := strconv.Atoi(splitT[0]) // 开始时间 1734426000
end, _ := strconv.Atoi(splitT[1]) // 结束时间 1734426108
if param.Timestamp >= int64(start) && param.Timestamp <= int64(end) {
splitF := strings.Split(splitMsg[1], "-") // 开始浮点~结束浮点 2652.33-2653.5299999999997
if len(splitF) >= 2 {
sf := decimal.RequireFromString(splitF[0]) // 开始浮点 2652.33
ef := decimal.RequireFromString(splitF[1]) // 结束浮点 2653.5299999999997
randomPrice := RandomBetween(sf.InexactFloat64(), ef.InexactFloat64())
price = decimal.NewFromFloat(randomPrice)
val.ChangePrice = price
if val.RestoreSetChangePrice {
val.RestoreChangePrice = price
}
SetValue_Forex(val.ForexCode, val)
}
break // 跳出循环
}
}
}
}
param.Close = price.InexactFloat64()
param.Open = val.ChangePrice.InexactFloat64()
if price.GreaterThan(decimal.NewFromFloat(param.High)) {
param.High = price.InexactFloat64()
}
if price.LessThan(decimal.NewFromFloat(param.Low)) {
param.Low = price.InexactFloat64()
}
forexJson := models.ForexJsonData{
Event: "CAS",
Pair: param.Pair,
Open: param.Open,
Close: param.Close,
High: param.High,
Low: param.Low,
Volume: param.Volume,
Timestamp: param.Timestamp,
}
applogger.Debug("交易对%v,插针数据:%v", param.Pair, forexJson)
return forexJson, true
}
// 在a和b之间生成平滑随机值
func RandomBetween(a, b float64) float64 {
// 确保a小于b
if a > b {
a, b = b, a
}
// 计算范围
rangeVal := (b - a)
// 在范围内生成随机数
return rand.Float64()*rangeVal + a
}
// 时间区间
func DivideTimeInterval(start, end time.Time, numIntervals int) map[int]string {
// 计算两个时间点之间的间隔
duration := end.Sub(start)
// 计算每个区间的持续时间
intervalDuration := duration / time.Duration(numIntervals)
// 生成区间起始时间列表
var msg = make(map[int]string)
for i := 0; i <= numIntervals; i++ {
subStart := start.Add(time.Duration(i) * intervalDuration).Unix()
subEnd := start.Add(time.Duration(i+1) * intervalDuration).Unix()
msg[i] = fmt.Sprintf("%v-%v", subStart, subEnd)
applogger.Debug("时间数据展示:%v,%v", i, msg[i])
}
return msg
}
// 浮点区间
func DivideFloatInterval(start, end float64, numIntervals int) map[int]string {
// 计算每个子区间的宽度
width := (end - start) / float64(numIntervals)
// 生成区间起始时间列表
var msg = make(map[int]string)
// 生成并打印子区间
for i := 0; i <= numIntervals; i++ {
subStart := start + width*float64(i)
subEnd := start + width*float64(i+1)
msg[i] = fmt.Sprintf("%v-%v", decimal.NewFromFloat(subStart), decimal.NewFromFloat(subEnd))
applogger.Debug("浮点数据展示:%v,%v", i, msg[i])
}
return msg
}