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.
431 lines
12 KiB
431 lines
12 KiB
2 months ago
|
package marketwsscliert
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"github.com/google/uuid"
|
||
|
"github.com/gorilla/websocket"
|
||
|
"github.com/shopspring/decimal"
|
||
|
"go.mongodb.org/mongo-driver/bson"
|
||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||
|
"go.mongodb.org/mongo-driver/mongo"
|
||
|
"strings"
|
||
|
"time"
|
||
|
"wss-pool/internal"
|
||
|
"wss-pool/internal/data"
|
||
|
red "wss-pool/internal/redis"
|
||
|
"wss-pool/logging/applogger"
|
||
|
"wss-pool/pkg/model"
|
||
|
models "wss-pool/pkg/model"
|
||
|
)
|
||
|
|
||
|
var messageStr chan []byte
|
||
|
var messageDayStr chan []byte
|
||
|
|
||
|
func init() {
|
||
|
messageStr = make(chan []byte)
|
||
|
messageDayStr = make(chan []byte)
|
||
|
}
|
||
|
|
||
|
// 外汇交易对实时报价
|
||
|
func subscribeMarketForexBakNew(conn *websocket.Conn) {
|
||
|
for {
|
||
|
_, msg, err := conn.ReadMessage()
|
||
|
if err != nil {
|
||
|
applogger.Error("err info:%v", err)
|
||
|
time.Sleep(50 * time.Second)
|
||
|
break
|
||
|
}
|
||
|
if strings.Contains(string(msg), "ping") ||
|
||
|
strings.Contains(string(msg), "subscribe success") ||
|
||
|
strings.Contains(string(msg), "\"ev\":\"C\"") ||
|
||
|
strings.Contains(string(msg), "\"ev\":\"T\"") ||
|
||
|
strings.Contains(string(msg), "pong") {
|
||
|
continue
|
||
|
}
|
||
|
var subModel model.FinnhubMessageNew
|
||
|
if err = json.Unmarshal(msg, &subModel); err != nil {
|
||
|
applogger.Error("subModel Unmarshal info111 err: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
var modelCl []model.ForexJsonData
|
||
|
if err = json.Unmarshal([]byte(subModel.Content), &modelCl); err != nil {
|
||
|
applogger.Error("subModel Unmarshal info222 err: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
for _, value := range modelCl {
|
||
|
//if value.Pair != "XAUUSD" {
|
||
|
// continue
|
||
|
//}
|
||
|
// TODO: 插针处理
|
||
|
forexJson, checkBool := RunModifyForexNew(value)
|
||
|
msgStr, err := json.Marshal(forexJson)
|
||
|
if err != nil {
|
||
|
applogger.Error("json.Marshal err: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
applogger.Debug("message info:%v", string(msgStr))
|
||
|
if checkBool {
|
||
|
// TODO: 启动插针数据推送(延缓数据推送)
|
||
|
messageStr <- msgStr
|
||
|
} else {
|
||
|
for k, db := range red.RedisClientMap {
|
||
|
err = db.Publish(fmt.Sprintf("%s.Forex", value.Pair), string(msgStr)).Err()
|
||
|
if err != nil {
|
||
|
applogger.Error("db", k, "存储失败:", err)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
func pinInsertionRun() {
|
||
|
go func() {
|
||
|
for msg := range messageStr {
|
||
|
var forexModel models.ForexJsonData
|
||
|
if err := json.Unmarshal(msg, &forexModel); err != nil {
|
||
|
applogger.Error("Run Unmarshal info err:", err)
|
||
|
continue
|
||
|
}
|
||
|
// 推送到redis
|
||
|
for k, db := range red.RedisClientMap {
|
||
|
err := db.Publish(fmt.Sprintf("%s.Forex", forexModel.Pair), string(msg)).Err()
|
||
|
if err != nil {
|
||
|
applogger.Error("db", k, "存储失败:", err)
|
||
|
}
|
||
|
}
|
||
|
// 写入Mongodb数据格式
|
||
|
t := time.Unix(forexModel.Timestamp, 0)
|
||
|
formatted := t.Format("2006-01-02 15:04:05")
|
||
|
dataStr := bson.D{
|
||
|
{"code", forexModel.Pair},
|
||
|
{"timestamp", formatted},
|
||
|
{"open_price", decimal.NewFromFloat(forexModel.Open).String()},
|
||
|
{"close_price", decimal.NewFromFloat(forexModel.Close).String()},
|
||
|
{"high_price", decimal.NewFromFloat(forexModel.High).String()},
|
||
|
{"low_price", decimal.NewFromFloat(forexModel.Low).String()},
|
||
|
{"volume", decimal.NewFromInt(int64(forexModel.Volume)).String()},
|
||
|
{"turnover", "0.00"},
|
||
|
}
|
||
|
if err := data.MgoInsertOne(data.ForexKLine, dataStr); err != nil {
|
||
|
applogger.Error("Insert info err:%v", err)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
}()
|
||
|
}
|
||
|
|
||
|
// 外汇交易对实时天报价
|
||
|
func subscribeMarketDayForexBakNew(conn *websocket.Conn) {
|
||
|
for {
|
||
|
_, msg, err := conn.ReadMessage()
|
||
|
if err != nil {
|
||
|
applogger.Error("err info:%v", err)
|
||
|
time.Sleep(50 * time.Second)
|
||
|
break
|
||
|
}
|
||
|
if strings.Contains(string(msg), "ping") ||
|
||
|
strings.Contains(string(msg), "subscribe success") ||
|
||
|
strings.Contains(string(msg), "\"ev\":\"C\"") ||
|
||
|
strings.Contains(string(msg), "\"ev\":\"T\"") ||
|
||
|
strings.Contains(string(msg), "pong") {
|
||
|
continue
|
||
|
}
|
||
|
var subModel model.FinnhubMessageNew
|
||
|
if err = json.Unmarshal(msg, &subModel); err != nil {
|
||
|
applogger.Error("subModel Unmarshal info111 err: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
var modelCl []model.ForexJsonData
|
||
|
if err = json.Unmarshal([]byte(subModel.Content), &modelCl); err != nil {
|
||
|
applogger.Error("subModel Unmarshal info222 err: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
for _, value := range modelCl {
|
||
|
// TODO: 插针处理
|
||
|
forexJson, checkBool := RunModifyForex(value)
|
||
|
msgStr, err := json.Marshal(forexJson)
|
||
|
if err != nil {
|
||
|
applogger.Error("json.Marshal err: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
applogger.Debug("message info:%v", string(msgStr))
|
||
|
if checkBool {
|
||
|
// TODO: 启动插针数据推送(延缓数据推送)
|
||
|
messageDayStr <- msgStr
|
||
|
} else {
|
||
|
for k, db := range red.RedisClientMap {
|
||
|
err = db.Publish(fmt.Sprintf("%s.DayForex", value.Pair), string(msgStr)).Err()
|
||
|
if err != nil {
|
||
|
applogger.Error("db", k, "存储失败:", err)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
func pinInsertionDayRun() {
|
||
|
go func() {
|
||
|
for msg := range messageDayStr {
|
||
|
var forexModel models.ForexJsonData
|
||
|
if err := json.Unmarshal(msg, &forexModel); err != nil {
|
||
|
applogger.Error("Run Unmarshal info err:", err)
|
||
|
continue
|
||
|
}
|
||
|
// 数据处理
|
||
|
for k, db := range red.RedisClientMap {
|
||
|
err := db.Publish(fmt.Sprintf("%s.Forex", forexModel.Pair), string(msg)).Err()
|
||
|
if err != nil {
|
||
|
applogger.Error("db", k, "存储失败:", err)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}()
|
||
|
}
|
||
|
|
||
|
// 外汇交易对买一卖一报价
|
||
|
func subscribeMarketForexQuoteBakNew(conn *websocket.Conn) {
|
||
|
for {
|
||
|
_, msg, err := conn.ReadMessage()
|
||
|
if err != nil {
|
||
|
applogger.Error("err info:%v", err)
|
||
|
time.Sleep(50 * time.Second)
|
||
|
break
|
||
|
}
|
||
|
msgStrOne := string(msg)
|
||
|
//applogger.Debug("ReadMessage data info:%v", msgStrOne)
|
||
|
|
||
|
if strings.Contains(msgStrOne, "ping") ||
|
||
|
strings.Contains(msgStrOne, "subscribe success") ||
|
||
|
strings.Contains(msgStrOne, "\"ev\":\"CAS\"") ||
|
||
|
strings.Contains(msgStrOne, "\"ev\":\"T\"") ||
|
||
|
strings.Contains(msgStrOne, "pong") {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
var subModel model.FinnhubMessageNew
|
||
|
if err = json.Unmarshal(msg, &subModel); err != nil {
|
||
|
applogger.Error("subModel Unmarshal info111 err: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
var modelCl []model.ForexLastQuote
|
||
|
if err = json.Unmarshal([]byte(subModel.Content), &modelCl); err != nil {
|
||
|
applogger.Error("subModel Unmarshal info222 err: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
for _, value := range modelCl {
|
||
|
msgStr, err := json.Marshal(value)
|
||
|
if err != nil {
|
||
|
applogger.Error("json.Marshal err: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
applogger.Debug("message info:%v", string(msgStr))
|
||
|
// Write to Redis for broadcasting
|
||
|
if len(value.P) == 0 {
|
||
|
continue
|
||
|
}
|
||
|
for k, db := range red.RedisClientMap {
|
||
|
err = db.Publish(fmt.Sprintf("%s.LastForex", value.P), string(msgStr)).Err()
|
||
|
if err != nil {
|
||
|
applogger.Error("db", k, "存储失败:", err)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 外汇交易对成交报价
|
||
|
func subscribeMarketForexTradeBakNew(conn *websocket.Conn) {
|
||
|
for {
|
||
|
_, msg, err := conn.ReadMessage()
|
||
|
if err != nil {
|
||
|
applogger.Error("err info:%v", err)
|
||
|
time.Sleep(50 * time.Second)
|
||
|
break
|
||
|
}
|
||
|
msgStrOne := string(msg)
|
||
|
//applogger.Debug("ReadMessage data info:%v", msgStrOne)
|
||
|
|
||
|
if strings.Contains(msgStrOne, "ping") ||
|
||
|
strings.Contains(msgStrOne, "subscribe success") ||
|
||
|
strings.Contains(msgStrOne, "\"ev\":\"CAS\"") ||
|
||
|
strings.Contains(msgStrOne, "\"ev\":\"C\"") ||
|
||
|
strings.Contains(msgStrOne, "pong") {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
var subModel model.FinnhubMessageNew
|
||
|
if err = json.Unmarshal(msg, &subModel); err != nil {
|
||
|
applogger.Error("subModel Unmarshal info111 err: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
var modelCl []model.ForexTrade
|
||
|
if err = json.Unmarshal([]byte(subModel.Content), &modelCl); err != nil {
|
||
|
applogger.Error("subModel Unmarshal info222 err: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
for _, value := range modelCl {
|
||
|
msgStr, err := json.Marshal(value)
|
||
|
if err != nil {
|
||
|
applogger.Error("json.Marshal err: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
applogger.Debug("message info:%v", string(msgStr))
|
||
|
for k, db := range red.RedisClientMap {
|
||
|
err = db.Publish(fmt.Sprintf("%s.TradeForex", value.Code), string(msgStr)).Err()
|
||
|
if err != nil {
|
||
|
applogger.Error("db", k, "存储失败:", err)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 外汇交易对成交报价存储
|
||
|
func subscribeMarketForexTradeBak2New(conn *websocket.Conn) {
|
||
|
for {
|
||
|
_, msg, err := conn.ReadMessage()
|
||
|
if err != nil {
|
||
|
applogger.Error("err info:%v", err)
|
||
|
time.Sleep(50 * time.Second)
|
||
|
break
|
||
|
}
|
||
|
msgStrOne := string(msg)
|
||
|
//applogger.Debug("ReadMessage data info:%v", msgStrOne)
|
||
|
|
||
|
if strings.Contains(msgStrOne, "ping") ||
|
||
|
strings.Contains(msgStrOne, "subscribe success") ||
|
||
|
strings.Contains(msgStrOne, "\"ev\":\"CAS\"") ||
|
||
|
strings.Contains(msgStrOne, "\"ev\":\"C\"") ||
|
||
|
strings.Contains(msgStrOne, "pong") {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
var subModel model.FinnhubMessageNew
|
||
|
if err = json.Unmarshal(msg, &subModel); err != nil {
|
||
|
applogger.Error("subModel Unmarshal info111 err: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
var modelCl []model.ForexTrade
|
||
|
if err = json.Unmarshal([]byte(subModel.Content), &modelCl); err != nil {
|
||
|
applogger.Error("subModel Unmarshal info222 err: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
var dataList []mongo.WriteModel
|
||
|
for _, v := range modelCl {
|
||
|
filter := bson.M{"tick_time": bson.M{"$eq": decimal.RequireFromString(v.TickTime).IntPart()}, "code": bson.M{"$eq": v.Code}}
|
||
|
update := bson.D{{"$set",
|
||
|
bson.D{
|
||
|
{"ev", v.Ev},
|
||
|
{"code", v.Code},
|
||
|
{"seq", v.Seq},
|
||
|
{"tick_time", decimal.RequireFromString(v.TickTime).IntPart()},
|
||
|
{"price", v.Price},
|
||
|
{"volume", v.Volume},
|
||
|
{"turnover", v.Turnover},
|
||
|
{"trade_direction", v.TradeDirection},
|
||
|
}}}
|
||
|
models := mongo.NewUpdateOneModel().SetFilter(filter).SetUpdate(update).SetUpsert(true)
|
||
|
dataList = append(dataList, models)
|
||
|
}
|
||
|
if len(dataList) > 0 {
|
||
|
if err = data.MgoBulkWrite(data.ForexTradeList, dataList); err != nil {
|
||
|
applogger.Error("forexTrade MgoBulkWrite err:%v", err)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 清理外汇成交报价数据信息
|
||
|
func DeleteForexTrade() {
|
||
|
dateList, err := data.MgoFind(data.ForexListBak, bson.M{})
|
||
|
if err != nil {
|
||
|
applogger.Error("MgoFind info err: %v", err)
|
||
|
return
|
||
|
}
|
||
|
//applogger.Info("MgoFind info len: %v", dateList)
|
||
|
for _, value := range dateList.([]primitive.M) {
|
||
|
code := value["symbol"].(string)
|
||
|
filter := bson.M{"code": code}
|
||
|
//applogger.Debug("清理数据:%v", filter)
|
||
|
if err = data.MgoDeleteMany100List(data.ForexTradeList, filter, code); err != nil {
|
||
|
applogger.Error("DeleteForexTrade MgoDeleteMany err :", err.Error())
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 每周一到周五0点0分0秒更新外汇交易对闭盘价
|
||
|
func ForexUpdateCode() {
|
||
|
dateList, err := data.MgoFind(data.ForexListBak, bson.M{})
|
||
|
if err != nil {
|
||
|
applogger.Error("MgoFind info err: %v", err)
|
||
|
return
|
||
|
}
|
||
|
var codeList []string
|
||
|
for _, value := range dateList.([]primitive.M) {
|
||
|
code := value["code"].(string)
|
||
|
codeList = append(codeList, code)
|
||
|
}
|
||
|
|
||
|
UrlBatchKline := "https://quote.tradeswitcher.com/quote-b-api/batch-kline?token=bf8f33c446c4494286eccaa57a2e6fac-c-app"
|
||
|
|
||
|
var dataPost model.ConstructParametersPost
|
||
|
for _, value := range codeList {
|
||
|
dataPost.Trace = uuid.New().String()
|
||
|
dataPost.Data.DataList = append(dataPost.Data.DataList, model.DataParameters{
|
||
|
Code: value,
|
||
|
KlineType: 1,
|
||
|
KlineTimestampEnd: 0,
|
||
|
QueryKlineNum: 1,
|
||
|
AdjustType: 0,
|
||
|
})
|
||
|
}
|
||
|
queryStr, err := json.Marshal(&dataPost)
|
||
|
if err != nil {
|
||
|
applogger.Error("解析json错误:%v", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
bodyStr, err := internal.HttpPost(UrlBatchKline, string(queryStr))
|
||
|
if err != nil {
|
||
|
applogger.Error("读取响应失败:%v", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
//applogger.Debug("响应内容:%v", bodyStr)
|
||
|
var klineNew model.KlinePostReturnStruct
|
||
|
if err = json.Unmarshal([]byte(bodyStr), &klineNew); err != nil {
|
||
|
applogger.Error("解析失败:%v", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
//applogger.Debug("响应内容:%v", klineNew)
|
||
|
var dataList []mongo.WriteModel
|
||
|
for _, v := range klineNew.Data.KlineList {
|
||
|
filter := bson.M{
|
||
|
"code": v.Code,
|
||
|
}
|
||
|
updateData := bson.M{}
|
||
|
for _, value := range v.KlineData {
|
||
|
updateData["openPrice"] = value.OpenPrice
|
||
|
updateData["highPrice"] = value.HighPrice
|
||
|
updateData["lowPrice"] = value.LowPrice
|
||
|
updateData["closePrice"] = value.ClosePrice
|
||
|
updateData["timestamp"] = value.Timestamp
|
||
|
break
|
||
|
}
|
||
|
update := bson.M{"$set": updateData}
|
||
|
models := mongo.NewUpdateOneModel().SetFilter(filter).SetUpdate(update).SetUpsert(true)
|
||
|
dataList = append(dataList, models)
|
||
|
}
|
||
|
if len(dataList) > 0 {
|
||
|
if err = data.MgoBulkWrite(data.ForexListBak, dataList); err != nil {
|
||
|
applogger.Error("MgoInsertMany err:%v", err)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|