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
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
|
||
|
}
|