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.
1176 lines
38 KiB
1176 lines
38 KiB
2 months ago
|
package business
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"github.com/360EntSecGroup-Skylar/excelize"
|
||
|
"github.com/google/uuid"
|
||
|
"github.com/shopspring/decimal"
|
||
|
"go.mongodb.org/mongo-driver/bson"
|
||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||
|
"go.mongodb.org/mongo-driver/mongo"
|
||
|
"go.uber.org/zap"
|
||
|
"math"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
"sync"
|
||
|
"time"
|
||
|
"wss-pool/cmd/common"
|
||
|
"wss-pool/config"
|
||
|
"wss-pool/dictionary"
|
||
|
"wss-pool/internal"
|
||
|
"wss-pool/internal/data"
|
||
|
red "wss-pool/internal/redis"
|
||
|
"wss-pool/logging/applogger"
|
||
|
"wss-pool/pkg/model"
|
||
|
"wss-pool/pkg/model/stock"
|
||
|
)
|
||
|
|
||
|
var TapsMapMu = map[int32]string{
|
||
|
1: "NYSE",
|
||
|
2: "NYSEARCA",
|
||
|
3: "NASDAQ",
|
||
|
}
|
||
|
|
||
|
var TapsMapMuNew = map[string]string{
|
||
|
"XNYS": "NYSE",
|
||
|
"BATS": "NYSE",
|
||
|
"XASE": "NYSE",
|
||
|
"ARCX": "NYSE",
|
||
|
"XNAS": "NASDAQ",
|
||
|
}
|
||
|
|
||
|
var CountryEx = map[string]string{
|
||
|
"Thailand": "SET",
|
||
|
"Indonesia": "IDX",
|
||
|
"Malaysia": "MYX",
|
||
|
"Singapore": "SGX",
|
||
|
"HongKong": "HKEX",
|
||
|
"Japan": "TSE",
|
||
|
}
|
||
|
|
||
|
var StockClosingPrice = map[string]string{
|
||
|
"US": "Stock:US:ClosePrice", //美股当天闭盘价
|
||
|
"USNew": "Stock:US:CloseNewPrice", //美股实时落盘价
|
||
|
"USBeforeClose": "Stock:US:BeforeClose", //美股上一次闭盘价
|
||
|
|
||
|
"Malaysia": "Stock:Malaysia:ClosePrice", //马股当天闭盘价
|
||
|
"MalaysiaNew": "Stock:Malaysia:CloseNewPrice", //马股实时落盘价
|
||
|
"MalaysiaBeforeClose": "Stock:Malaysia:BeforeClose", //马股上一次闭盘价
|
||
|
|
||
|
"Thailand": "Stock:Thailand:ClosePrice", //泰股当天闭盘价
|
||
|
"ThailandNew": "Stock:Thailand:CloseNewPrice", //泰股实时落盘价
|
||
|
"ThailandBeforeClose": "Stock:Thailand:BeforeClose", //泰股上一次闭盘价
|
||
|
|
||
|
"Indonesia": "Stock:Indonesia:ClosePrice", //印尼股当天闭盘价
|
||
|
"IndonesiaNew": "Stock:Indonesia:CloseNewPrice", //印尼股实时落盘价
|
||
|
"IndonesiaBeforeClose": "Stock:Indonesia:BeforeClose", //印尼股上一次闭盘价
|
||
|
|
||
|
"India": "Stock:India:ClosePrice", //印度股当天闭盘价
|
||
|
"IndiaNew": "Stock:India:CloseNewPrice", //印度股实时落盘价
|
||
|
"IndiaBeforeClose": "Stock:India:BeforeClose", //印度股上一次闭盘价
|
||
|
|
||
|
"StockIndex": "Stock:Index:ClosePrice", //指数当天闭盘价
|
||
|
"StockIndexNew": "Stock:Index:CloseNewPrice", //指数实时落盘价
|
||
|
"StockIndexBeforeClose": "Stock:Index:BeforeClose", //指数股上一次闭盘价
|
||
|
|
||
|
"Singapore": "Stock:Singapore:ClosePrice", //新加坡当天闭盘价
|
||
|
"SingaporeNew": "Stock:Singapore:CloseNewPrice", //新加坡股实时落盘价
|
||
|
"SingaporeBeforeClose": "Stock:Singapore:BeforeClose", //新加坡股上一次闭盘价
|
||
|
|
||
|
"HongKong": "Stock:HongKong:ClosePrice", //港股当天闭盘价
|
||
|
"HongKongNew": "Stock:HongKong:CloseNewPrice", //港股实时落盘价
|
||
|
"HongKongBeforeClose": "Stock:HongKong:BeforeClose", //港股上一次闭盘价
|
||
|
|
||
|
"OptionUS": "Stock:OptionUS:ClosePrice", //期权美股当天闭盘价
|
||
|
"OptionUSNew": "Stock:OptionUS:CloseNewPrice", //期权美股实时落盘价
|
||
|
"OptionUSBeforeClose": "Stock:OptionUS:BeforeClose", //期权美股上一次闭盘价
|
||
|
|
||
|
"OptionIndia": "Option:India:ClosePrice", //期权印度股当天闭盘价
|
||
|
"OptionIndiaNew": "Option:India:CloseNewPrice", //期权印度股实时落盘价
|
||
|
"OptionIndiaBeforeClose": "Option:India:BeforeClose", //期权印度股上一次闭盘价
|
||
|
"OptionIndiaPrice": "Option:India:List",
|
||
|
|
||
|
"UK": "Stock:UK:ClosePrice", //英股当天闭盘价
|
||
|
"UKNew": "Stock:UK:CloseNewPrice", //英股实时落盘价
|
||
|
"UKBeforeClose": "Stock:UK:BeforeClose", //英股上一次闭盘价
|
||
|
|
||
|
"Germany": "Stock:Germany:ClosePrice", //德股当天闭盘价
|
||
|
"GermanyNew": "Stock:Germany:CloseNewPrice", //德股实时落盘价
|
||
|
"GermanyBeforeClose": "Stock:Germany:BeforeClose", //德股上一次闭盘价
|
||
|
|
||
|
"France": "Stock:France:ClosePrice", //法股当天闭盘价
|
||
|
"FranceNew": "Stock:France:CloseNewPrice", //法股实时落盘价
|
||
|
"FranceBeforeClose": "Stock:France:BeforeClose", //法股上一次闭盘价
|
||
|
|
||
|
"Brazil": "Stock:Brazil:ClosePrice", //巴西当天闭盘价
|
||
|
"BrazilNew": "Stock:Brazil:CloseNewPrice", //巴西实时落盘价
|
||
|
"BrazilBeforeClose": "Stock:Brazil:BeforeClose", //巴西上一次闭盘价
|
||
|
|
||
|
"Japan": "Stock:Japan:ClosePrice", //日本当天闭盘价
|
||
|
"JapanNew": "Stock:Japan:CloseNewPrice", //日本实时落盘价
|
||
|
"JapanBeforeClose": "Stock:Japan:BeforeClose", //日本上一次闭盘价
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
mutexMap = sync.RWMutex{}
|
||
|
NewPriceMap = make(map[string]string)
|
||
|
IsRealFlase int = 2
|
||
|
StockCountryMap = map[string]string{
|
||
|
"US": "TSLA.US",
|
||
|
"Thailand": "SET:AAV.Thailand",
|
||
|
"Indonesia": "IDX:GOTO.Indonesia",
|
||
|
"India": "NSE:SUZLON.India",
|
||
|
"Malaysia": "MYX:MAYBANK.Malaysia",
|
||
|
"Singapore": "SGX:D05.Singapore",
|
||
|
"HongKong": "HKEX:9888.HongKong",
|
||
|
"UK": "LSE:BRBY.UK",
|
||
|
"France": "EURONEXT:RMS.France",
|
||
|
"Germany": "FWB:TMV.Germany",
|
||
|
"Brazil": "BMFBOVESPA:BBAS3.Brazil",
|
||
|
"Japan": "TSE:1380.Japan",
|
||
|
}
|
||
|
StockCountryIsValidMap = map[string]bool{
|
||
|
"US": false,
|
||
|
"Thailand": false,
|
||
|
"Indonesia": false,
|
||
|
"India": false,
|
||
|
"Malaysia": false,
|
||
|
"Singapore": false,
|
||
|
"HongKong": false,
|
||
|
"UK": false,
|
||
|
"France": false,
|
||
|
"Germany": false,
|
||
|
"Brazil": false,
|
||
|
"Japan": false,
|
||
|
}
|
||
|
StockIsValidMutex = sync.RWMutex{}
|
||
|
)
|
||
|
|
||
|
// UpdateStockUS Daily update of US stock list data【ws.eodhistoricaldata.com】
|
||
|
func UpdateStockUS() {
|
||
|
red.RedisInitMap(common.GetRedisDBMore(config.Config.Redis.DbMore))
|
||
|
filter := bson.M{"Country": "US", "IsReal": bson.M{"$ne": IsRealFlase}}
|
||
|
dateList, err := data.MgoFind(data.StockList, filter)
|
||
|
if err != nil {
|
||
|
applogger.Error("MgoFind info err: %v", err)
|
||
|
return
|
||
|
}
|
||
|
day := common.TimeToNows().Weekday()
|
||
|
if day == time.Sunday {
|
||
|
applogger.Debug("周日 无数据")
|
||
|
return
|
||
|
}
|
||
|
for _, value := range dateList.([]primitive.M) {
|
||
|
code := TypeCheck(value["Code"])
|
||
|
//定时任务 最长休假 算 10 天
|
||
|
// today := common.TimeToNows().AddDate(0, 0, -10).Unix()
|
||
|
// eodModel, _ := PreviousClose(code)
|
||
|
// if len(eodModel.Results) <= 0 {
|
||
|
// applogger.Error("close price null")
|
||
|
// continue
|
||
|
// }
|
||
|
// dateStrs := common.ConvertToTimezones(eodModel.Results[0].T)
|
||
|
// if dateStrs.Unix() < today {
|
||
|
// applogger.Error(code, dateStrs, "超出时间范围")
|
||
|
// //updateYesterdayClose(code, "US")
|
||
|
// continue
|
||
|
// }
|
||
|
// yesterday := dateStrs
|
||
|
//Loop:
|
||
|
// yesterday = yesterday.AddDate(0, 0, -1)
|
||
|
// yesterdayClose, _ := UsData(code, yesterday.Format("2006-01-02"))
|
||
|
// if yesterdayClose == "" {
|
||
|
// goto Loop
|
||
|
// }
|
||
|
Loop:
|
||
|
res := GetFinnhubBeforClose(code)
|
||
|
if strings.Contains(res.Error, "API limit reached") { //防止被限制
|
||
|
time.Sleep(6 * time.Second)
|
||
|
goto Loop
|
||
|
}
|
||
|
if !res.C.GreaterThan(decimal.Zero) {
|
||
|
applogger.Error(code, "close price null")
|
||
|
continue
|
||
|
}
|
||
|
filterS := bson.D{{"Code", bson.M{
|
||
|
"$eq": code,
|
||
|
}}, {"Country", bson.M{
|
||
|
"$eq": "US",
|
||
|
}}}
|
||
|
dp, _ := res.DP.Float64() //股价百分比变化
|
||
|
updateData := bson.M{
|
||
|
"$set": bson.M{
|
||
|
"BeforeClose": res.PC.String(),
|
||
|
"DateStr": common.ConvertToTimezone(res.T * 1000),
|
||
|
"DP": dp,
|
||
|
"YesterdayClose": res.C.String()}}
|
||
|
red.HsetMap(StockClosingPrice["US"], code, res.C.String())
|
||
|
red.HsetMap(StockClosingPrice["USBeforeClose"], code, res.PC.String())
|
||
|
red.HsetMap(StockClosingPrice["USNew"], code, "0")
|
||
|
applogger.Debug("update data info:%v", updateData)
|
||
|
if err := data.MgoUpdateOne(data.StockList, filterS, updateData); err != nil {
|
||
|
applogger.Error("MgoBulkWrite update err:%v", err)
|
||
|
return
|
||
|
}
|
||
|
// TODO: 更改副表 没有公用数据的服务不需要 暂用redis 参数
|
||
|
dbs := common.GetRedisDBMore(config.Config.Redis.DbMore)
|
||
|
if len(dbs) > 1 {
|
||
|
applogger.Info("StockListAdd update table db", dbs[1])
|
||
|
data.MgoUpdateOne(fmt.Sprintf("%s%s", data.StockList, dbs[1]), filterS, updateData)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func UpdateOpenPrice() {
|
||
|
red.RedisClient = red.RedisInit(config.Config.Redis.DbTen)
|
||
|
stocks, _, pageTotal := GetStockAll("US", 1, UsPageSize)
|
||
|
wg := sync.WaitGroup{}
|
||
|
end := common.TimeToNows().Format("2006-01-02")
|
||
|
for _, value := range stocks {
|
||
|
wg.Add(1)
|
||
|
go func(end, code string) {
|
||
|
defer wg.Done()
|
||
|
res := GetBeforClose(code, "1", "day", end, end)
|
||
|
if len(res.Results) > 0 {
|
||
|
applogger.Debug("US open price %v ,%v", code, res.Results[0].O.String())
|
||
|
red.Hset(StockClosingPrice["US"], code, res.Results[0].O.String())
|
||
|
}
|
||
|
}(end, value.Code)
|
||
|
}
|
||
|
wg.Wait()
|
||
|
for i := int64(2); i <= pageTotal; i++ {
|
||
|
stocks, _, _ := GetStockAll("US", i, UsPageSize)
|
||
|
wg := sync.WaitGroup{}
|
||
|
for _, value := range stocks {
|
||
|
wg.Add(1)
|
||
|
go func(end, code string) {
|
||
|
defer wg.Done()
|
||
|
res := GetBeforClose(code, "1", "day", end, end)
|
||
|
if len(res.Results) > 0 {
|
||
|
applogger.Debug("US open price %v ,%v", code, res.Results[0].O.String())
|
||
|
red.Hset(StockClosingPrice["US"], code, res.Results[0].O.String())
|
||
|
}
|
||
|
}(end, value.Code)
|
||
|
}
|
||
|
wg.Wait()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func updateYesterdayClose(code, country string) {
|
||
|
filterS := bson.D{{"Code", bson.M{
|
||
|
"$eq": code,
|
||
|
}}, {"Country", bson.M{
|
||
|
"$eq": country,
|
||
|
}}}
|
||
|
updateData := bson.M{
|
||
|
"$set": bson.M{
|
||
|
"YesterdayClose": ""}}
|
||
|
red.Hset(StockClosingPrice[country], code, "0")
|
||
|
red.Hset(StockClosingPrice[fmt.Sprintf("%sNew", country)], code, "0")
|
||
|
red.Hset(StockClosingPrice[fmt.Sprintf("%sBeforeClose", country)], code, "0")
|
||
|
if err := data.MgoUpdateOne(data.StockList, filterS, updateData); err != nil {
|
||
|
applogger.Error("MgoBulkWrite update err:%v", err)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func UpdateYesterdayCloseIs(code, country, yesterdayClose, beforeClose string) {
|
||
|
filterS := bson.D{{"Code", bson.M{
|
||
|
"$eq": code,
|
||
|
}}, {"Country", bson.M{
|
||
|
"$eq": country,
|
||
|
}}}
|
||
|
updateData := bson.M{
|
||
|
"$set": bson.M{
|
||
|
"YesterdayClose": yesterdayClose}}
|
||
|
red.Hset(StockClosingPrice[country], code, yesterdayClose)
|
||
|
red.Hset(StockClosingPrice[fmt.Sprintf("%sNew", country)], code, 0)
|
||
|
red.Hset(StockClosingPrice[fmt.Sprintf("%sBeforeClose", country)], code, beforeClose)
|
||
|
if err := data.MgoUpdateOne(data.StockList, filterS, updateData); err != nil {
|
||
|
applogger.Error("MgoBulkWrite update err:%v", err)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func GetBeforClose(code string, multiplier, timespan, start, end string) stock.PreviousCloseResponse {
|
||
|
var eodModel stock.PreviousCloseResponse
|
||
|
url := fmt.Sprintf("https://%v/v2/aggs/ticker/%v/range/%v/%v/%v/%v?adjusted=true&sort=desc&%v",
|
||
|
config.Config.ShareGather.PolygonHost, code, multiplier, timespan, start, end, fmt.Sprintf("apiKey=%v", config.Config.ShareGather.PolygonKey))
|
||
|
applogger.Debug("UrlHttp getBeforClose info: %v", url)
|
||
|
bodyStr, err := internal.HttpGet(url)
|
||
|
if err != nil {
|
||
|
applogger.Error("Failed to query data:%v", err)
|
||
|
return eodModel
|
||
|
}
|
||
|
if err = json.Unmarshal([]byte(bodyStr), &eodModel); err != nil {
|
||
|
applogger.Error("eodModel json Unmarshal err: %v", err)
|
||
|
return eodModel
|
||
|
}
|
||
|
return eodModel
|
||
|
}
|
||
|
|
||
|
func GetFinnhubBeforClose(code string) stock.PreviousCloseRes {
|
||
|
var eodModel stock.PreviousCloseRes
|
||
|
url := fmt.Sprintf("https://%vquote?symbol=%s&token=%s",
|
||
|
config.Config.FinnhubUs.FinnhubHost, code, config.Config.FinnhubUs.FinnhubKey)
|
||
|
applogger.Debug("UrlHttp getBeforClose info: %v", url)
|
||
|
bodyStr, err := internal.HttpGet(url)
|
||
|
fmt.Println(bodyStr)
|
||
|
if err != nil {
|
||
|
applogger.Error("Failed to query data:%v", err)
|
||
|
return eodModel
|
||
|
}
|
||
|
if err = json.Unmarshal([]byte(bodyStr), &eodModel); err != nil {
|
||
|
applogger.Error("eodModel json Unmarshal err: %v", err)
|
||
|
return eodModel
|
||
|
}
|
||
|
return eodModel
|
||
|
}
|
||
|
|
||
|
// 更新交易所
|
||
|
func UpdateStockUSTape() {
|
||
|
filter := bson.M{"Country": "US"}
|
||
|
dateList, err := data.MgoFind(data.StockList, filter)
|
||
|
if err != nil {
|
||
|
applogger.Error("MgoFind info err: %v", err)
|
||
|
return
|
||
|
}
|
||
|
for _, value := range dateList.([]primitive.M) {
|
||
|
code := TypeCheck(value["Code"])
|
||
|
eodModel, _ := TradesTape(code)
|
||
|
filterS := bson.D{{"Code", bson.M{
|
||
|
"$eq": code,
|
||
|
}}, {"Country", bson.M{
|
||
|
"$eq": "US",
|
||
|
}}}
|
||
|
if len(eodModel.Results) <= 0 {
|
||
|
continue
|
||
|
}
|
||
|
updateData := bson.M{
|
||
|
"$set": bson.M{
|
||
|
"Code": code,
|
||
|
"Tape": eodModel.Results[0].Tape}}
|
||
|
applogger.Debug("update data info:%v", updateData)
|
||
|
if err := data.MgoUpdateOne(data.StockList, filterS, updateData); err != nil {
|
||
|
applogger.Error("MgoBulkWrite update err:%v", err)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 推送
|
||
|
func StockPyWs(param model.StockParam, country string) {
|
||
|
param.Token = ""
|
||
|
msgStr, err := json.Marshal(param)
|
||
|
if err != nil {
|
||
|
applogger.Error("json.Marshal err: %v", err)
|
||
|
return
|
||
|
}
|
||
|
//applogger.Info("last date info: %v", string(msgStr))
|
||
|
// Write to Redis for broadcasting
|
||
|
red.PublishMap(fmt.Sprintf("%s.%s", param.Symbol, country), string(msgStr))
|
||
|
}
|
||
|
|
||
|
func IsPriceTime(symbol, price, country string) bool {
|
||
|
//fmt.Println(symbol, price, country)
|
||
|
mutexMap.RLock()
|
||
|
val := NewPriceMap[fmt.Sprintf("%s-%s", country, symbol)]
|
||
|
mutexMap.RUnlock()
|
||
|
if val != "" {
|
||
|
strs := strings.Split(val, "-")
|
||
|
if len(strs) > 0 {
|
||
|
timeInt, _ := strconv.ParseInt(strs[1], 10, 64)
|
||
|
if strs[0] == price && common.TimeToNow() < timeInt {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
mutexMap.Lock()
|
||
|
NewPriceMap[fmt.Sprintf("%s-%s", country, symbol)] = fmt.Sprintf("%s-%d", price, common.TimeToNow()+30)
|
||
|
mutexMap.Unlock()
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
// 推送
|
||
|
func StockPyWsStockIndex(param model.StockIndexParam, country string) {
|
||
|
param.Token = ""
|
||
|
param.IsStockIndex = true
|
||
|
msgStr, err := json.Marshal(param)
|
||
|
if err != nil {
|
||
|
applogger.Error("json.Marshal err: %v", err)
|
||
|
return
|
||
|
}
|
||
|
//applogger.Info("last date info: %v", string(msgStr))
|
||
|
// Write to Redis for broadcasting
|
||
|
red.PublishMap(fmt.Sprintf("%s.%s", param.StockCode, country), string(msgStr))
|
||
|
}
|
||
|
|
||
|
// 期权列表推送
|
||
|
func StockPyWsOptionList(param model.OptionPolygon, country string) string {
|
||
|
param.IsOptionList = true
|
||
|
msgStr, err := json.Marshal(param)
|
||
|
if err != nil {
|
||
|
applogger.Error("json.Marshal err: %v", err)
|
||
|
return ""
|
||
|
}
|
||
|
//applogger.Info("last date info: %v", string(msgStr))
|
||
|
// Write to Redis for broadcasting
|
||
|
red.PublishMap(fmt.Sprintf("%s.%s", param.Stock, country), string(msgStr))
|
||
|
return string(msgStr)
|
||
|
}
|
||
|
|
||
|
// 期权详情推送
|
||
|
func StockPyWsOptionInfo(param model.OptionInfoParam, country string) string {
|
||
|
param.IsOptionInfo = true
|
||
|
param.Token = ""
|
||
|
msgStr, err := json.Marshal(param)
|
||
|
if err != nil {
|
||
|
applogger.Error("json.Marshal err: %v", err)
|
||
|
return ""
|
||
|
}
|
||
|
//applogger.Info("StockPyWsOptionInfo info: %v", string(msgStr))
|
||
|
// Write to Redis for broadcasting
|
||
|
red.PublishMap(fmt.Sprintf("%s.%s", param.Stock, country), string(msgStr))
|
||
|
return string(msgStr)
|
||
|
}
|
||
|
|
||
|
// 期权详情Exchange推送
|
||
|
func StockPyWsOptionInfoExchange(param model.OptionInfoExchange, country string) string {
|
||
|
param.IsOptionInfo = true
|
||
|
msgStr, err := json.Marshal(param)
|
||
|
if err != nil {
|
||
|
applogger.Error("json.Marshal err: %v", err)
|
||
|
return ""
|
||
|
}
|
||
|
applogger.Info("StockPyWsOptionInfoExchange info: %v", string(msgStr))
|
||
|
red.PublishMap(fmt.Sprintf("%s.%s", param.Stock, country), string(msgStr))
|
||
|
return string(msgStr)
|
||
|
}
|
||
|
|
||
|
func OptionResPrice(param model.StrikePrice, key, code string, isClose bool, optionDate, expiration string) string {
|
||
|
result := model.StrikePrice{}
|
||
|
resStr, _ := red.Hget(code, key)
|
||
|
param.DueDate = common.OptionTime(expiration)
|
||
|
if resStr != "" {
|
||
|
json.Unmarshal([]byte(resStr), &result)
|
||
|
param.BeforeClose = result.BeforeClose
|
||
|
param.YesterdayClose = result.YesterdayClose
|
||
|
param.CloseDate = result.CloseDate
|
||
|
if isClose && optionDate != result.CloseDate { //多次传闭盘价
|
||
|
param.BeforeClose = result.YesterdayClose
|
||
|
param.YesterdayClose = param.Price
|
||
|
param.Price = "0"
|
||
|
param.CloseDate = optionDate
|
||
|
} else if isClose && optionDate == result.CloseDate {
|
||
|
param.BeforeClose = result.BeforeClose
|
||
|
param.YesterdayClose = param.Price
|
||
|
param.Price = "0"
|
||
|
}
|
||
|
}
|
||
|
msgStr, err := json.Marshal(param)
|
||
|
if err != nil {
|
||
|
applogger.Error("json.Marshal err: %v", err)
|
||
|
return ""
|
||
|
}
|
||
|
red.HsetMap(code, key, string(msgStr))
|
||
|
return string(msgStr)
|
||
|
}
|
||
|
|
||
|
func DelOptionHash() {
|
||
|
red.RedisClient = red.RedisInit(config.Config.Redis.DbTen)
|
||
|
keys := red.Scan("Option:India:List")
|
||
|
for _, key := range keys {
|
||
|
res, _ := red.HGetAll(key)
|
||
|
for k, val := range res {
|
||
|
result := model.StrikePrice{}
|
||
|
json.Unmarshal([]byte(val), &result)
|
||
|
if common.TimeToNow() >= (result.DueDate + 24*60*60) {
|
||
|
applogger.Info("DelOptionHash : expireTime %v", result.DueDate, key, k)
|
||
|
red.HDel(key, k)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func UpdateStockBeforeClose(symbol, price, country string) {
|
||
|
//if val, ok := NewPriceMap[fmt.Sprintf("%s-%s", country, symbol)]; ok && val == price {
|
||
|
// applogger.Info("new price", fmt.Sprintf("%s-%s", country, symbol), price)
|
||
|
// return
|
||
|
//}
|
||
|
red.HsetMap(StockClosingPrice[fmt.Sprintf("%sNew", country)], symbol, price)
|
||
|
//NewPriceMap[fmt.Sprintf("%s-%s", country, symbol)] = price
|
||
|
}
|
||
|
|
||
|
// UpdateStockUSBak api.polygon.io Update US stock list data
|
||
|
func UpdateStockUSBak() {
|
||
|
yesterday := time.Now().AddDate(0, 0, -1).Format("2006-01-02")
|
||
|
before := time.Now().AddDate(0, 0, -2).Format("2006-01-02")
|
||
|
|
||
|
// 从mongodb中获取股票代码
|
||
|
filter := bson.M{"Country": "USA", "YesterdayClose": bson.M{"$ne": ""}, "BeforeClose": bson.M{"$ne": ""}}
|
||
|
dateList, err := data.MgoFind(data.StockList, filter)
|
||
|
if err != nil {
|
||
|
applogger.Error("MgoFind info err: %v", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
for _, value := range dateList.([]primitive.M) {
|
||
|
code := TypeCheck(value["Code"])
|
||
|
yesterdayClose, err := UsData(code, yesterday)
|
||
|
if err != nil || len(yesterdayClose) == 0 {
|
||
|
applogger.Error("yesterdayClose ConstructorData info err: %v", err)
|
||
|
yesterdayClose = TypeCheck(value["YesterdayClose"])
|
||
|
}
|
||
|
beforeClose, err := UsData(code, before)
|
||
|
if err != nil || len(beforeClose) == 0 {
|
||
|
applogger.Error("beforeClose ConstructorData info err: %v", err)
|
||
|
beforeClose = TypeCheck(value["BeforeClose"])
|
||
|
}
|
||
|
|
||
|
applogger.Debug("data info:%v-----%v-----%v", code, yesterdayClose, beforeClose)
|
||
|
|
||
|
filterS := bson.D{{"Code", bson.M{
|
||
|
"$eq": code,
|
||
|
}}}
|
||
|
updateData := bson.M{
|
||
|
"$set": bson.M{
|
||
|
"Code": code,
|
||
|
"YesterdayClose": yesterdayClose,
|
||
|
"BeforeClose": beforeClose}}
|
||
|
|
||
|
applogger.Debug("update data info:%v", updateData)
|
||
|
if err := data.MgoUpdateOne(data.StockList, filterS, updateData); err != nil {
|
||
|
applogger.Error("MgoBulkWrite update err:%v", err)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// UsData Obtaining the closing price of US stocks through time【api.polygon.io】
|
||
|
func UsData(code, date string) (string, error) {
|
||
|
url := fmt.Sprintf("https://%v/v1/open-close/%v/%v?apiKey=%v&adjusted=true", config.Config.ShareGather.PolygonHost, code, date, config.Config.ShareGather.PolygonKey)
|
||
|
bodyStr, err := internal.HttpGet(url)
|
||
|
if err != nil {
|
||
|
applogger.Error("Failed to query data:%v", err)
|
||
|
return "", err
|
||
|
}
|
||
|
applogger.Debug("url info:%v", url)
|
||
|
|
||
|
if strings.Contains(bodyStr, ",\"message\":") {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
var eodModel stock.UsDateClose
|
||
|
if err = json.Unmarshal([]byte(bodyStr), &eodModel); err != nil {
|
||
|
applogger.Error("Unmarshal err: %v---%v", eodModel.Symbol, err)
|
||
|
return "", err
|
||
|
}
|
||
|
return eodModel.Close.String(), err
|
||
|
}
|
||
|
|
||
|
func UsNewPrice(code string) {
|
||
|
red.RedisClient = red.RedisInit(config.Config.Redis.DbEleven)
|
||
|
//定时任务 最长休假 算 10 天
|
||
|
today := common.TimeToNows().AddDate(0, 0, -10).Unix()
|
||
|
eodModel, _ := PreviousClose(code)
|
||
|
if len(eodModel.Results) <= 0 {
|
||
|
applogger.Error("close price null")
|
||
|
return
|
||
|
}
|
||
|
fmt.Println(eodModel)
|
||
|
dateStrs := common.ConvertToTimezones(eodModel.Results[0].T)
|
||
|
if dateStrs.Unix() < today {
|
||
|
applogger.Error(code, dateStrs, "超出时间范围")
|
||
|
//updateYesterdayClose(code, "US")
|
||
|
return
|
||
|
}
|
||
|
yesterday := dateStrs
|
||
|
Loop:
|
||
|
yesterday = yesterday.AddDate(0, 0, -1)
|
||
|
yesterdayClose, _ := UsData(code, yesterday.Format("2006-01-02"))
|
||
|
if yesterdayClose == "" {
|
||
|
goto Loop
|
||
|
}
|
||
|
filterS := bson.D{{"Code", bson.M{
|
||
|
"$eq": code,
|
||
|
}}, {"Country", bson.M{
|
||
|
"$eq": "US",
|
||
|
}}}
|
||
|
updateData := bson.M{
|
||
|
"$set": bson.M{
|
||
|
"Code": code,
|
||
|
"BeforeClose": yesterdayClose,
|
||
|
"DateStr": dateStrs.Format("2006-01-02"),
|
||
|
"Vol": eodModel.Results[0].V.IntPart(),
|
||
|
"YesterdayClose": eodModel.Results[0].C.String()}}
|
||
|
red.Hset(StockClosingPrice["US"], code, eodModel.Results[0].C.String())
|
||
|
red.Hset(StockClosingPrice["USBeforeClose"], code, yesterdayClose)
|
||
|
red.Hset(StockClosingPrice["USNew"], code, "0")
|
||
|
applogger.Debug("update data info:%v", updateData)
|
||
|
if err := data.MgoUpdateOne(data.StockList, filterS, updateData); err != nil {
|
||
|
applogger.Error("MgoBulkWrite update err:%v", err)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 倒数据
|
||
|
func SymbolToStock(country string) {
|
||
|
if country == "" {
|
||
|
return
|
||
|
}
|
||
|
red.RedisClient = red.RedisInit(config.Config.Redis.DbTen)
|
||
|
config.Config.Mongodb.DbHost = "10.154.0.5"
|
||
|
data.Mgo_init(config.Config.Mongodb)
|
||
|
filter := bson.M{"Country": country}
|
||
|
if country == "StockIndex" {
|
||
|
filter = bson.M{}
|
||
|
}
|
||
|
res := make([]stock.StockPolygonS, 0)
|
||
|
tableName := data.StockList
|
||
|
if country == "StockIndex" {
|
||
|
tableName = data.StockIndexList
|
||
|
}
|
||
|
data.MgoFindRes(tableName, filter, &res)
|
||
|
config.Config.Mongodb.DbHost = "10.154.0.10"
|
||
|
data.Mgo_init(config.Config.Mongodb)
|
||
|
var dataList []mongo.WriteModel
|
||
|
fmt.Println(len(res))
|
||
|
for _, value := range res {
|
||
|
filter := bson.D{{"Code", bson.M{
|
||
|
"$eq": value.Code,
|
||
|
}}, {"Country", bson.M{
|
||
|
"$eq": value.Locale,
|
||
|
}}}
|
||
|
update := bson.D{{"$set", bson.D{
|
||
|
{"Code", value.Code},
|
||
|
{"Name", value.Name},
|
||
|
{"Country", value.Locale},
|
||
|
{"Exchange", value.PrimaryExchange},
|
||
|
{"Currency", value.Currency},
|
||
|
{"Intro", value.Intro},
|
||
|
{"Type", value.Type},
|
||
|
{"Cik", value.CIK},
|
||
|
{"ShareClassFigi", value.ShareClassFigi},
|
||
|
{"YesterdayClose", value.YesterdayClose},
|
||
|
{"BeforeClose", value.BeforeClose},
|
||
|
{"Tape", value.Tape},
|
||
|
{"State", value.State},
|
||
|
{"NumericCode", value.NumericCode},
|
||
|
{"DateStr", value.DateStr},
|
||
|
{"Sort", value.Sort},
|
||
|
{"LogoUrl", value.LogoUrl}}}}
|
||
|
models := mongo.NewUpdateOneModel().SetFilter(filter).SetUpdate(update).SetUpsert(true)
|
||
|
dataList = append(dataList, models)
|
||
|
//red.Hset(StockClosingPrice[country], value.Code, value.YesterdayClose)
|
||
|
//red.Hset(StockClosingPrice[fmt.Sprintf("%sBeforeClose", country)], value.Code, value.BeforeClose)
|
||
|
//red.Hset(StockClosingPrice[fmt.Sprintf("%sNew", country)], value.Code, "0")
|
||
|
}
|
||
|
// fmt.Println(2222)
|
||
|
if err := data.MgoBulkWrite(tableName, dataList); err != nil {
|
||
|
applogger.Error("MgoInsertMany err:%v", err)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// SymbolToStockList
|
||
|
//
|
||
|
// @Description: 将旧的美股数据导入新的项目
|
||
|
// @param country
|
||
|
func SymbolToStockList(country string) {
|
||
|
config.Config.Mongodb.DbHost = "35.189.116.242"
|
||
|
data.Mgo_init(config.Config.Mongodb)
|
||
|
res := make([]stock.StockListBak, 0)
|
||
|
data.MgoFindRes(data.StockList, bson.M{"Country": country}, &res)
|
||
|
applogger.Debug("查询股票列表:%v", len(res))
|
||
|
|
||
|
config.Config.Mongodb.DbHost = "104.198.117.66"
|
||
|
data.Mgo_init(config.Config.Mongodb)
|
||
|
var dataList []mongo.WriteModel
|
||
|
for _, value := range res {
|
||
|
filter := bson.D{{"Code", bson.M{
|
||
|
"$eq": value.Code,
|
||
|
}}, {"Country", bson.M{
|
||
|
"$eq": value.Country,
|
||
|
}}}
|
||
|
update := bson.D{{"$set", bson.D{
|
||
|
{"Country", value.Country},
|
||
|
{"Code", value.Code},
|
||
|
{"BeforeClose", value.BeforeClose},
|
||
|
{"Cik", value.Cik},
|
||
|
{"CompositeFigi", value.CompositeFigi},
|
||
|
{"Currency", value.Currency},
|
||
|
{"Exchange", value.Exchange},
|
||
|
{"Name", value.Name},
|
||
|
{"ShareClassFigi", value.ShareClassFigi},
|
||
|
{"Type", value.Type},
|
||
|
{"YesterdayClose", value.YesterdayClose},
|
||
|
{"DP", value.DP},
|
||
|
{"DateStr", value.DateStr}}}}
|
||
|
models := mongo.NewUpdateOneModel().SetFilter(filter).SetUpdate(update).SetUpsert(true)
|
||
|
dataList = append(dataList, models)
|
||
|
}
|
||
|
|
||
|
applogger.Debug("倒入数据:%v", len(dataList))
|
||
|
|
||
|
if err := data.MgoBulkWrite(data.StockList, dataList); err != nil {
|
||
|
applogger.Error("MgoInsertMany err:%v", err)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 倒数据
|
||
|
func SymbolToStockInfo(country string) {
|
||
|
if country == "" {
|
||
|
return
|
||
|
}
|
||
|
config.Config.Mongodb.DbHost = "34.93.29.102"
|
||
|
data.Mgo_init(config.Config.Mongodb)
|
||
|
config.Config.Mongodb.DbHost = "47.236.120.73"
|
||
|
client := data.Mgo_inits(config.Config.Mongodb)
|
||
|
fmt.Println(country)
|
||
|
for _, period := range dictionary.StockSouthAsiaListTimes {
|
||
|
tableName := data.GetStockSouthAsiaTableName(country, period)
|
||
|
if country == "StockIndex" {
|
||
|
tableName = data.GetStockIndixKlineTableName(period)
|
||
|
}
|
||
|
fmt.Println(tableName)
|
||
|
res, _, pageTotal := GetStockIndoAll(tableName, 1, 100, period)
|
||
|
var dataList []mongo.WriteModel
|
||
|
for _, v := range res {
|
||
|
filter := bson.M{"timestamp": bson.M{"$eq": v.Ts}, "symbol": bson.M{"$eq": v.Symbol}}
|
||
|
update := bson.D{{"$set", bson.D{
|
||
|
{"symbol", v.Symbol},
|
||
|
{"stock_code", v.StockCode},
|
||
|
{"stock_name", v.StockName},
|
||
|
{"open_price", v.OpenPrice},
|
||
|
{"high_price", v.HighPrice},
|
||
|
{"low_price", v.LowPrice},
|
||
|
{"close_price", v.ClosePrice},
|
||
|
{"vol", v.Vol},
|
||
|
{"turnover_price_total", v.TurnoverPriceTotal},
|
||
|
{"price_total", v.PriceTotal},
|
||
|
{"price_code", v.PriceCode},
|
||
|
{"country", v.Country},
|
||
|
{"timestamp", v.Ts},
|
||
|
}}}
|
||
|
models := mongo.NewUpdateOneModel().SetFilter(filter).SetUpdate(update).SetUpsert(true)
|
||
|
dataList = append(dataList, models)
|
||
|
}
|
||
|
if err := data.MgoBulkWrites(client, tableName, dataList); err != nil {
|
||
|
applogger.Error("stock MgoInsertMany err:%v", err)
|
||
|
}
|
||
|
fmt.Println(pageTotal)
|
||
|
//for i := int64(2); i <= pageTotal; i++ {
|
||
|
// res, _, _ := GetStockIndoAll(tableName, i, 100, period)
|
||
|
// fmt.Println(period, i)
|
||
|
// for _, v := range res {
|
||
|
// filter := bson.M{"timestamp": bson.M{"$eq": v.Ts}, "symbol": bson.M{"$eq": v.Symbol}}
|
||
|
// update := bson.D{{"$set", bson.D{
|
||
|
// {"symbol", v.Symbol},
|
||
|
// {"stock_code", v.StockCode},
|
||
|
// {"stock_name", v.StockName},
|
||
|
// {"open_price", v.OpenPrice},
|
||
|
// {"high_price", v.HighPrice},
|
||
|
// {"low_price", v.LowPrice},
|
||
|
// {"close_price", v.ClosePrice},
|
||
|
// {"vol", v.Vol},
|
||
|
// {"turnover_price_total", v.TurnoverPriceTotal},
|
||
|
// {"price_total", v.PriceTotal},
|
||
|
// {"price_code", v.PriceCode},
|
||
|
// {"country", v.Country},
|
||
|
// {"timestamp", v.Ts},
|
||
|
// }}}
|
||
|
// models := mongo.NewUpdateOneModel().SetFilter(filter).SetUpdate(update).SetUpsert(true)
|
||
|
// dataList = append(dataList, models)
|
||
|
// }
|
||
|
// if err := data.MgoBulkWrites(client, tableName, dataList); err != nil {
|
||
|
// applogger.Error("stock MgoInsertMany err:%v", err)
|
||
|
// }
|
||
|
//}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func GetStockIndoAll(tableName string, pageNum, pageSize int64, period string) ([]model.StockMogoParams, int64, int64) {
|
||
|
filter := bson.M{}
|
||
|
if period == "1hour" {
|
||
|
filter = bson.M{"timestamp": bson.M{"$gte": time.Now().AddDate(0, 0, -20).UnixMilli()}}
|
||
|
} else if period == "1day" {
|
||
|
filter = bson.M{"timestamp": bson.M{"$gte": time.Now().AddDate(0, -6, 0).UnixMilli()}}
|
||
|
}
|
||
|
projection := bson.M{}
|
||
|
res := make([]model.StockMogoParams, 0)
|
||
|
total, _ := data.MgoFindTotal(tableName, filter)
|
||
|
data.MgoPagingFindStructProjection(tableName, filter, projection, pageSize, pageNum, -1, &res)
|
||
|
return res, total, int64(math.Ceil(float64(total) / float64(pageSize)))
|
||
|
}
|
||
|
|
||
|
func SymbolNews(country string) {
|
||
|
config.Config.Mongodb.DbHost = "104.198.117.66"
|
||
|
data.Mgo_init(config.Config.Mongodb)
|
||
|
filter := bson.M{"country": country}
|
||
|
res := make([]model.StockNews, 0)
|
||
|
data.MgoFindRes(data.StockNews, filter, &res)
|
||
|
config.Config.Mongodb.DbHost = "35.186.148.111"
|
||
|
data.Mgo_init(config.Config.Mongodb)
|
||
|
var bsonEod []interface{}
|
||
|
for _, v := range res {
|
||
|
bsonEod = append(bsonEod, bson.D{
|
||
|
{"country", v.Country},
|
||
|
{"pubdate", v.Pubdate},
|
||
|
{"title", v.Title},
|
||
|
{"link", v.Link},
|
||
|
{"source", v.Source},
|
||
|
{"code", v.Code},
|
||
|
})
|
||
|
}
|
||
|
if err := data.MgoInsertMany(data.StockNews, bsonEod); err != nil {
|
||
|
applogger.Error("MgoInsertMany info err: %v", err)
|
||
|
return
|
||
|
}
|
||
|
//}
|
||
|
fmt.Println(1111)
|
||
|
}
|
||
|
|
||
|
// 更改股票code结构(美股不需要更改)
|
||
|
func UpdateStockCode() {
|
||
|
red.RedisClient = red.RedisInit(config.Config.Redis.DbEleven)
|
||
|
filter := bson.M{}
|
||
|
dateList, err := data.MgoFind(data.StockList, filter)
|
||
|
if err != nil {
|
||
|
applogger.Error("MgoFind info err: %v", err)
|
||
|
return
|
||
|
}
|
||
|
for _, value := range dateList.([]primitive.M) {
|
||
|
if value["Code"] == nil || value["Country"] == nil || (value["Tape"] == nil && value["Exchange"] == nil) {
|
||
|
continue
|
||
|
}
|
||
|
code := value["Code"].(string)
|
||
|
var exchange, symbol string
|
||
|
country := value["Country"].(string)
|
||
|
if country == "US" {
|
||
|
exchange = TapsMapMu[value["Tape"].(int32)]
|
||
|
symbol = code
|
||
|
} else {
|
||
|
exchange = value["Exchange"].(string)
|
||
|
if exchange == "" && country != "India" {
|
||
|
exchange = CountryEx[country]
|
||
|
}
|
||
|
if exchange == "" {
|
||
|
applogger.Error("没有值", country, symbol, exchange)
|
||
|
continue
|
||
|
}
|
||
|
symbol = fmt.Sprintf("%s:%s", exchange, code)
|
||
|
red.HDel(StockClosingPrice[country], code)
|
||
|
red.Hset(StockClosingPrice[country], symbol, value["YesterdayClose"])
|
||
|
red.HDel(StockClosingPrice[fmt.Sprintf("%sBeforeClose", country)], code)
|
||
|
red.Hset(StockClosingPrice[fmt.Sprintf("%sBeforeClose", country)], symbol, value["BeforeClose"])
|
||
|
red.Hset(StockClosingPrice[fmt.Sprintf("%sNew", country)], code, "0")
|
||
|
red.Hset(StockClosingPrice[fmt.Sprintf("%sNew", country)], symbol, "0")
|
||
|
}
|
||
|
filterList := bson.M{"Code": code, "Country": country}
|
||
|
if err = data.MgoUpdateOne(
|
||
|
data.StockList,
|
||
|
filterList,
|
||
|
bson.D{{"$set", bson.D{
|
||
|
{"Code", symbol},
|
||
|
{"Exchange", exchange},
|
||
|
{"Symbol", code}}}}); err != nil {
|
||
|
applogger.Error(symbol, err)
|
||
|
}
|
||
|
applogger.Info(symbol, exchange, code, country)
|
||
|
}
|
||
|
}
|
||
|
func UpdateStockUsCode() {
|
||
|
red.RedisClient = red.RedisInit(config.Config.Redis.DbEleven)
|
||
|
filter := bson.M{"Country": "US"}
|
||
|
dateList, err := data.MgoFind(data.StockList, filter)
|
||
|
if err != nil {
|
||
|
applogger.Error("MgoFind info err: %v", err)
|
||
|
return
|
||
|
}
|
||
|
for _, value := range dateList.([]primitive.M) {
|
||
|
if value["Code"] == nil || value["Country"] == nil || value["Exchange"] == nil {
|
||
|
continue
|
||
|
}
|
||
|
codeList := strings.Split(value["Code"].(string), ".")
|
||
|
if len(codeList) == 0 {
|
||
|
continue
|
||
|
}
|
||
|
code := codeList[0]
|
||
|
var exchange, symbol string
|
||
|
country := value["Country"].(string)
|
||
|
if country == "US" {
|
||
|
exchange = TapsMapMuNew[value["Exchange"].(string)]
|
||
|
symbol = code
|
||
|
}
|
||
|
if err = data.MgoUpdateOne(
|
||
|
data.StockList,
|
||
|
bson.M{"Code": value["Code"].(string), "Country": country},
|
||
|
bson.D{{"$set", bson.D{
|
||
|
{"Code", symbol},
|
||
|
//{"Exchange", exchange},
|
||
|
{"Symbol", code}}}}); err != nil {
|
||
|
applogger.Error(symbol, err)
|
||
|
}
|
||
|
applogger.Info(symbol, exchange, code, country)
|
||
|
}
|
||
|
}
|
||
|
func UpdateStockExchange() {
|
||
|
filter := bson.M{
|
||
|
"Country": "India",
|
||
|
}
|
||
|
dateList, err := data.MgoFind(data.StockList, filter)
|
||
|
if err != nil {
|
||
|
applogger.Error("MgoFind info err: %v", err)
|
||
|
return
|
||
|
}
|
||
|
applogger.Info("total ", len(dateList.([]primitive.M)))
|
||
|
var i int
|
||
|
for _, value := range dateList.([]primitive.M) {
|
||
|
if value["Exchange"] == nil || value["Exchange"].(string) == "" {
|
||
|
i++
|
||
|
fmt.Println(i)
|
||
|
code := value["Code"].(string)
|
||
|
filter = bson.M{"stock_code": code}
|
||
|
res, _ := data.MgoFinds(data.GetStockSouthAsiaTableName("India", "1day"), filter, int64(1))
|
||
|
if len(res) > 0 {
|
||
|
exchange := strings.Split(res[0]["symbol"].(string), ":")[0]
|
||
|
applogger.Info(exchange, code)
|
||
|
filterList := bson.M{"Code": code,
|
||
|
"Country": "India",
|
||
|
}
|
||
|
//applogger.Info(exchange,code)
|
||
|
if err := data.MgoUpdateOne(data.StockList, filterList, bson.D{{"$set", bson.D{
|
||
|
{"Exchange", exchange}}}}); err != nil {
|
||
|
}
|
||
|
} else {
|
||
|
applogger.Error(code, "no data")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 外汇代码数据信息更新
|
||
|
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
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
func MalaysiaStockUpdate() {
|
||
|
data.Mgo_init(config.Config.Mongodb)
|
||
|
f, err := excelize.OpenFile("final.xlsx")
|
||
|
if err != nil {
|
||
|
fmt.Println(err)
|
||
|
return
|
||
|
}
|
||
|
// 获取 Sheet1 上所有单元格
|
||
|
rows := f.GetRows("Sheet1")
|
||
|
for k, row := range rows {
|
||
|
if k == 0 {
|
||
|
continue
|
||
|
}
|
||
|
fmt.Println(k, row)
|
||
|
symbol := strings.TrimSpace(row[0])
|
||
|
numericCode := strings.TrimSpace(row[1])
|
||
|
filter := bson.M{"Code": common.GetNewCode("MYX", symbol, "Malaysia"),
|
||
|
"Country": "Malaysia",
|
||
|
}
|
||
|
updateData := bson.D{{"$set", bson.D{
|
||
|
{"NumericCode", numericCode}}}}
|
||
|
if err := data.MgoUpdateOne(data.StockList, filter, updateData); err != nil {
|
||
|
applogger.Error(err.Error())
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func SendIndiaInfo() {
|
||
|
for {
|
||
|
if !common.IsOpening("India") {
|
||
|
applogger.Debug(time.Now().Format("2006-01-02 15:04:05"), " it's not opening time -----------------------------end")
|
||
|
continue
|
||
|
}
|
||
|
url := fmt.Sprintf("%s/india/spots/new/add", config.Config.SendIn.URL)
|
||
|
param := fmt.Sprintf(`[{"stock_code":"%s","symbol":"%s","country":"india","price":%v,"vol":%d,"ts":%d,"token":"asdfsnl123jlknl3nksdf32345ln98sdfsfs8891232nsdfsdfsdfsdxcfvbhnfgh"}]`,
|
||
|
common.GetOldCode(config.Config.SendIn.Symbol), config.Config.SendIn.Symbol, config.Config.SendIn.Price, config.Config.SendIn.Vol, time.Now().UnixMilli())
|
||
|
|
||
|
applogger.Info(param)
|
||
|
|
||
|
bodyStr, err := internal.HttpPost(url, param)
|
||
|
if err != nil {
|
||
|
applogger.Error("Failed to query data:%v", err)
|
||
|
}
|
||
|
|
||
|
applogger.Info(bodyStr)
|
||
|
time.Sleep(2 * time.Minute)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func CheckStock() {
|
||
|
time.Sleep(1 * time.Minute)
|
||
|
red.RedisClient = red.RedisInit(config.Config.Redis.DbTen)
|
||
|
for k, _ := range StockClosedDataList {
|
||
|
go func(k string) {
|
||
|
if strings.Contains(config.Config.TgBot.NoWarn, k) {
|
||
|
fmt.Println(k, "no warn")
|
||
|
return
|
||
|
} else if k == "US" && !common.IsOpeningUS() {
|
||
|
applogger.Debug(common.TimeToNows().Format("2006-01-02 15:04:05"), k, " it's not opening time -----------------------------end")
|
||
|
return
|
||
|
} else if (k == "Thailand" || k == "Indonesia" || k == "India" || k == "Malaysia" || k == "Singapore" || k == "HongKong" || k == "UK" || k == "France" || k == "Germany" || k == "Japan") && !common.IsOpening(k) {
|
||
|
applogger.Debug(common.TimeToNows().Format("2006-01-02 15:04:05"), k, " it's not opening time -----------------------------end")
|
||
|
return
|
||
|
}
|
||
|
fmt.Println(k)
|
||
|
fmt.Println(StockCountryMap[k])
|
||
|
pubSub := red.RedisClient.Subscribe(StockCountryMap[k])
|
||
|
defer func() {
|
||
|
pubSub.Close()
|
||
|
}()
|
||
|
_, err := pubSub.Receive()
|
||
|
if err != nil {
|
||
|
applogger.Error("failed to receive from control PubSub,%v", zap.Error(err))
|
||
|
return
|
||
|
}
|
||
|
go func(k string) {
|
||
|
time.Sleep(10 * time.Minute)
|
||
|
if !StockCountryIsValidMap[k] {
|
||
|
common.TgBotSendMsg(fmt.Sprintf("%s %s %s 市场 %s 股票 行情异常,请注意!", common.TimeToNows().Format("2006-01-02 15:04:05"), config.Config.TgBot.Server, k, StockCountryMap[k]))
|
||
|
}
|
||
|
}(k)
|
||
|
ch := pubSub.Channel()
|
||
|
for msg := range ch {
|
||
|
applogger.Info("Subscribe date:%v", msg.Payload)
|
||
|
StockIsValidMutex.Lock()
|
||
|
StockCountryIsValidMap[k] = true
|
||
|
StockIsValidMutex.Unlock()
|
||
|
return
|
||
|
}
|
||
|
}(k)
|
||
|
}
|
||
|
time.Sleep(13 * time.Minute)
|
||
|
}
|
||
|
|
||
|
func SymbolCode(country string) {
|
||
|
red.RedisClient = red.RedisInit(config.Config.Redis.DbTen)
|
||
|
data.Mgo_init(config.Config.Mongodb)
|
||
|
filter := bson.M{"Country": country}
|
||
|
res := make([]stock.StockPolygonS, 0)
|
||
|
tableName := data.StockList
|
||
|
data.MgoFindRes(tableName, filter, &res)
|
||
|
var dataList []mongo.WriteModel
|
||
|
//fmt.Println(len(res))
|
||
|
for _, value := range res {
|
||
|
filter := bson.D{{"Code", bson.M{
|
||
|
"$eq": value.Code,
|
||
|
}}, {"Country", bson.M{
|
||
|
"$eq": value.Locale,
|
||
|
}}}
|
||
|
exchange := value.PrimaryExchange
|
||
|
if value.Locale == "Thailand" {
|
||
|
exchange = "SET"
|
||
|
|
||
|
} else if value.Locale == "Indonesia" {
|
||
|
exchange = "IDX"
|
||
|
|
||
|
} else if value.Locale == "US" {
|
||
|
switch value.Tape {
|
||
|
case 1:
|
||
|
exchange = "NYSE"
|
||
|
case 2:
|
||
|
exchange = "NYSE-ARCA/NYSE-American"
|
||
|
case 3:
|
||
|
exchange = "NASDAQ"
|
||
|
}
|
||
|
}
|
||
|
code := fmt.Sprintf("%s.%s", value.Code, exchange)
|
||
|
//if exchange == "" {
|
||
|
// fmt.Println(value.Code)
|
||
|
//}
|
||
|
//continue
|
||
|
update := bson.D{{"$set", bson.D{
|
||
|
{"Code", code},
|
||
|
{"Exchange", exchange},
|
||
|
{"Symbol", value.Code}}}}
|
||
|
models := mongo.NewUpdateOneModel().SetFilter(filter).SetUpdate(update).SetUpsert(true)
|
||
|
dataList = append(dataList, models)
|
||
|
red.Hset(StockClosingPrice[value.Locale], value.Code, value.YesterdayClose)
|
||
|
red.Hset(StockClosingPrice[fmt.Sprintf("%sBeforeClose", value.Locale)], value.Code, value.BeforeClose)
|
||
|
red.Hset(StockClosingPrice[fmt.Sprintf("%sNew", value.Locale)], value.Code, "0")
|
||
|
}
|
||
|
if err := data.MgoBulkWrite(tableName, dataList); err != nil {
|
||
|
applogger.Error("MgoInsertMany err:%v", err)
|
||
|
return
|
||
|
}
|
||
|
}
|