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.
813 lines
30 KiB
813 lines
30 KiB
package processor
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/shopspring/decimal"
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
"wss-pool/cmd/common"
|
|
"wss-pool/config"
|
|
"wss-pool/dictionary"
|
|
"wss-pool/internal"
|
|
"wss-pool/internal/data"
|
|
"wss-pool/internal/data/business"
|
|
red "wss-pool/internal/redis"
|
|
"wss-pool/logging/applogger"
|
|
"wss-pool/pkg/model"
|
|
"wss-pool/pkg/model/stock"
|
|
)
|
|
|
|
var Token = "asdfsnl123jlknl3nksdf32345ln98sdfsfs8891232nsdfsdfsdfsdxcfvbhnfgh"
|
|
var TapsMap = map[string]int{
|
|
"NYSE": 1,
|
|
"NYSEARCA": 2,
|
|
"NASDAQ": 3,
|
|
}
|
|
|
|
func UsMessage(c *gin.Context) {
|
|
param := model.ClientMessageParam{}
|
|
err := c.BindJSON(¶m)
|
|
if err != nil {
|
|
applogger.Error("BindJSON", err.Error())
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "param error", internal.QueryError))
|
|
return
|
|
} else if param.Token != Token {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "token error", internal.QueryError))
|
|
return
|
|
}
|
|
for _, message := range param.Data {
|
|
msgStr, _ := json.Marshal(message)
|
|
business.JudgeHsetMap("US", business.StockClosingPrice[fmt.Sprintf("%sNew", "US")], message.S, message.Cl.String())
|
|
business.JudgePublishMap("US", message.S, fmt.Sprintf("%s.%s", message.S, "US"), string(msgStr))
|
|
}
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, "", "ok"))
|
|
}
|
|
|
|
func StockInfoAdd(c *gin.Context) {
|
|
param := make([]model.StockParam, 0)
|
|
err := c.BindJSON(¶m)
|
|
total := len(param)
|
|
if err != nil {
|
|
applogger.Error("BindJSON", err.Error())
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "param error", internal.QueryError))
|
|
return
|
|
} else if total <= 0 {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "param null", internal.QueryError))
|
|
return
|
|
} else if param[0].Token != Token {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "token error", internal.QueryError))
|
|
return
|
|
} else if param[0].Country == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "country error", internal.QueryError))
|
|
return
|
|
}
|
|
country := common.CapitalizeFirstLetter(param[0].Country)
|
|
var dataList []mongo.WriteModel
|
|
applogger.Debug("stock info add param total: %d", total)
|
|
for _, v := range param {
|
|
var price string
|
|
//if v.Country == "indonesia" {
|
|
// price = strconv.FormatFloat(v.Price, 'f', -1, 64)
|
|
//} else {
|
|
//price = strconv.FormatFloat(v.Price, 'f', 2, 64)
|
|
price = strconv.FormatFloat(v.Price, 'f', -1, 64)
|
|
//v.Price, err = strconv.ParseFloat(price, 64)
|
|
//if err != nil {
|
|
// applogger.Error(v.Country, v.StockCode, err)
|
|
//}
|
|
// }
|
|
//if !common.GetIndiaStockBool(v.Symbol,country) {
|
|
// applogger.Error("not india stock :%v", v.Symbol)
|
|
// continue
|
|
//}
|
|
if !business.IsPriceTime(v.Symbol, price, country) {
|
|
continue
|
|
}
|
|
business.StockWs(v, country)
|
|
//更新最新价格
|
|
//business.UpdateStockBeforeClose(v.Symbol, price, country)
|
|
business.JudgeHsetMap(country, business.StockClosingPrice[fmt.Sprintf("%sNew", country)], v.Symbol, price)
|
|
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},
|
|
{"price", v.Price},
|
|
{"up_down_rate", v.UpDownRate.String()},
|
|
{"up_down", v.UpDown.String()},
|
|
{"trade_v", v.TradeV.String()},
|
|
{"trade_k", v.TradeK},
|
|
{"vol", v.Vol},
|
|
{"turnover_price_total", v.TurnoverPriceTotal.String()},
|
|
{"price_total", v.PriceTotal},
|
|
{"p_e", v.PE},
|
|
{"eps", v.Eps},
|
|
{"employees_number", v.EmployeesNumber},
|
|
{"plate", v.Plate},
|
|
{"desc", v.Desc},
|
|
{"price_code", v.PriceCode},
|
|
{"country", v.Country},
|
|
{"timestamp", v.Ts},
|
|
}}}
|
|
models := mongo.NewUpdateOneModel().SetFilter(filter).SetUpdate(update).SetUpsert(true)
|
|
dataList = append(dataList, models)
|
|
}
|
|
if len(dataList) > 0 {
|
|
if err := data.MgoBulkWrite(data.GetStockTableName(country), dataList); err != nil {
|
|
applogger.Error("stock MgoInsertMany err:%v", err)
|
|
}
|
|
}
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, "", "ok"))
|
|
}
|
|
|
|
func UpdateImg(c *gin.Context) {
|
|
// 获取上传文件
|
|
file, err := c.FormFile("image")
|
|
if err != nil {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, fmt.Sprintf("file error %s", err.Error()), internal.QueryError))
|
|
return
|
|
}
|
|
//不能大于10M
|
|
if file.Size > 10*1024*1024 {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, fmt.Sprintf("file too big"), internal.QueryError))
|
|
return
|
|
}
|
|
// 打开上传文件
|
|
src, err := file.Open()
|
|
if err != nil {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, fmt.Sprintf("file error %s", err.Error()), internal.QueryError))
|
|
return
|
|
}
|
|
defer src.Close()
|
|
name := fmt.Sprintf("%d-%s", time.Now().Unix(), file.Filename)
|
|
if err := common.UpdateImage(name, src); err != nil {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, fmt.Sprintf("file error %s", err.Error()), internal.QueryError))
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, common.Path+name, "ok"))
|
|
}
|
|
|
|
func Visit(c *gin.Context) {
|
|
fileName := internal.ReplaceStr(c.Query("fileName"))
|
|
if fileName == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, fmt.Sprintf("fileName error "), internal.QueryError))
|
|
return
|
|
}
|
|
url, err := common.VisitImage(fileName)
|
|
if err != nil {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, fmt.Sprintf("file error %s", err.Error()), internal.QueryError))
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, url, "ok"))
|
|
}
|
|
|
|
func StockListAdd(c *gin.Context) {
|
|
param := stock.StockList{}
|
|
err := c.BindJSON(¶m)
|
|
fmt.Println(param)
|
|
if err != nil {
|
|
applogger.Error("BindJSON", err.Error())
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "param error", internal.QueryError))
|
|
return
|
|
} else if len(param.Results) <= 0 {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "param null", internal.QueryError))
|
|
return
|
|
} else if param.Token != Token {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "token error", internal.QueryError))
|
|
return
|
|
} else if param.Results[0].Code == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "ticker error", internal.QueryError))
|
|
return
|
|
} else if param.Results[0].Locale == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "locale error", internal.QueryError))
|
|
return
|
|
} else if param.Results[0].PrimaryExchange == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "primary exchange error", internal.QueryError))
|
|
return
|
|
}
|
|
////遇到排重 直接返回
|
|
//if len(param.Results) == 1 {
|
|
// value := param.Results[0]
|
|
// if !common.GetIndiaStockBool(fmt.Sprintf("%s:%s", value.PrimaryExchange, value.Code),common.CapitalizeFirstLetter(value.Locale)) {
|
|
// c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, "", "ok"))
|
|
// return
|
|
// }
|
|
//}
|
|
var dataList []mongo.WriteModel
|
|
for _, value := range param.Results {
|
|
//if !common.IsLetter(value.Code) {
|
|
// applogger.Debug(value.Code, "包含其他符号")
|
|
// continue
|
|
//}
|
|
locale := common.CapitalizeFirstLetter(value.Locale)
|
|
value.Code = common.GetNewCode(value.PrimaryExchange, value.Code, locale)
|
|
filter := bson.D{{"Code", bson.M{
|
|
"$eq": value.Code,
|
|
}}, {"Country", bson.M{
|
|
"$eq": locale,
|
|
}}}
|
|
update := bson.D{{"$set", bson.D{
|
|
{"Code", value.Code},
|
|
{"Name", value.Name},
|
|
{"Country", locale},
|
|
{"Exchange", value.PrimaryExchange},
|
|
{"Symbol", common.GetOldCode(value.Code)},
|
|
{"Currency", value.Currency},
|
|
{"Intro", value.Intro},
|
|
{"LogoUrl", value.LogoUrl}}}}
|
|
//第二次
|
|
if value.Currency == "" && value.YesterdayClose != "" {
|
|
_, err := decimal.NewFromString(value.YesterdayClose)
|
|
if err != nil {
|
|
applogger.Debug(value.Code, value.YesterdayClose, err.Error())
|
|
continue
|
|
}
|
|
value.DateStr = strings.TrimSpace(value.DateStr)
|
|
//if common.TimeToNows().Format("2006-01-02") != value.DateStr {
|
|
// applogger.Error(value.Code, "不是今日的闭盘价")
|
|
// continue
|
|
//}
|
|
update = bson.D{{"$set", bson.D{
|
|
{"YesterdayClose", value.YesterdayClose}, //上一次 闭盘价
|
|
{"Vol", value.Vol}, //当天的交易量
|
|
{"BeforeClose", value.BeforeClose},
|
|
{"ClosePrice", "0"},
|
|
{"Symbol", common.GetOldCode(value.Code)},
|
|
{"Exchange", value.PrimaryExchange},
|
|
{"IsSharia", value.IsSharia}, //是否符合伊斯兰股票 只针对 马来、印尼市场 其他市场不需要
|
|
{"DateStr", value.DateStr},
|
|
}}}
|
|
red.HsetMap(business.StockClosingPrice[locale], value.Code, value.YesterdayClose)
|
|
red.HsetMap(business.StockClosingPrice[fmt.Sprintf("%sBeforeClose", locale)], value.Code, value.BeforeClose)
|
|
red.HsetMap(business.StockClosingPrice[fmt.Sprintf("%sNew", locale)], value.Code, "0")
|
|
}
|
|
models := mongo.NewUpdateOneModel().SetFilter(filter).SetUpdate(update).SetUpsert(true)
|
|
dataList = append(dataList, models)
|
|
}
|
|
if len(dataList) > 0 {
|
|
if err := data.MgoBulkWrite(data.StockList, dataList); err != nil {
|
|
applogger.Error("MgoInsertMany err:%v", err)
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "operation failure", internal.QueryError))
|
|
return
|
|
}
|
|
// TODO: 更改副表 没有公用数据的服务不需要 暂用redis 参数
|
|
dbs := common.GetRedisDBMore(config.Config.Redis.DbMore)
|
|
if len(dbs) > 1 {
|
|
applogger.Info("StockListAdd update table db", dbs[1])
|
|
data.MgoBulkWrite(fmt.Sprintf("%s%s", data.StockList, dbs[1]), dataList)
|
|
}
|
|
} else {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "error operation repetition", internal.QueryError))
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, "", "ok"))
|
|
}
|
|
|
|
func StockListUpdate(c *gin.Context) {
|
|
param := stock.StockList{}
|
|
err := c.BindJSON(¶m)
|
|
if err != nil {
|
|
applogger.Error("BindJSON", err.Error())
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "param error", internal.QueryError))
|
|
return
|
|
} else if len(param.Results) <= 0 {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "param null", internal.QueryError))
|
|
return
|
|
} else if param.Token != Token {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "token error", internal.QueryError))
|
|
return
|
|
} else if param.Results[0].Code == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "ticker error", internal.QueryError))
|
|
return
|
|
} else if param.Results[0].Locale == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "locale error", internal.QueryError))
|
|
return
|
|
}
|
|
for _, value := range param.Results {
|
|
locale := common.CapitalizeFirstLetter(value.Locale)
|
|
value.Code = common.GetNewCode(value.PrimaryExchange, value.Code, locale)
|
|
filter := bson.D{{"Code", bson.M{
|
|
"$eq": value.Code,
|
|
}}, {"Country", bson.M{
|
|
"$eq": common.CapitalizeFirstLetter(value.Locale),
|
|
}}}
|
|
updateData := bson.D{{"$set", bson.D{
|
|
{"Name", value.Name},
|
|
{"Country", common.CapitalizeFirstLetter(value.Locale)},
|
|
{"Exchange", value.PrimaryExchange},
|
|
{"Currency", value.Currency},
|
|
{"Intro", value.Intro},
|
|
{"LogoUrl", value.LogoUrl}}}}
|
|
if err := data.MgoUpdateOne(data.StockList, filter, updateData); err != nil {
|
|
applogger.Error("MgoInsertMany info err: %v", err)
|
|
//return
|
|
}
|
|
postData := make(map[string]string)
|
|
postData["stock_code"] = value.Code
|
|
postData["stock_name"] = value.Name
|
|
postData["tape"] = value.PrimaryExchange
|
|
postData["country"] = fmt.Sprintf("%d", business.StockClosedDataList[common.CapitalizeFirstLetter(value.Locale)])
|
|
applogger.Info("php ", postData)
|
|
bodyStr, err := internal.HttpPostFrom(config.Config.PhpHost.URL, postData)
|
|
if err != nil {
|
|
applogger.Error("Failed to query data:%v", err)
|
|
}
|
|
applogger.Info(bodyStr)
|
|
}
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, "", "ok"))
|
|
}
|
|
|
|
func StockListGet(c *gin.Context) {
|
|
country := strings.TrimSpace(c.Query("country"))
|
|
isDeficiency := strings.TrimSpace(c.Query("is_deficiency")) // true 查找缺失数据股票 false 查找全部
|
|
sourceVal := strings.TrimSpace(c.Query("source")) // 1 tradingview 2 其他
|
|
source, _ := strconv.Atoi(sourceVal)
|
|
token := internal.ReplaceStr(c.Query("token"))
|
|
fmt.Println("source : ", source)
|
|
if token != Token {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "token error", internal.QueryError))
|
|
return
|
|
} else if country == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "country error", internal.QueryError))
|
|
return
|
|
}
|
|
country = common.CapitalizeFirstLetter(internal.ReplaceStr(country))
|
|
filter := bson.M{"Country": country}
|
|
if isDeficiency == "true" {
|
|
filter = bson.M{"Country": country, "Name": bson.M{"$exists": false}, "YesterdayClose": bson.M{"$ne": ""}}
|
|
}
|
|
if source != 0 {
|
|
filter = bson.M{"Country": country, "Source": source}
|
|
}
|
|
projection := bson.M{"Code": 1, "Country": 1, "Symbol": 1, "Exchange": 1, "Source": 1, "Name": 1}
|
|
sort := bson.M{}
|
|
var md stock.MgoPageSize
|
|
md.Total, _ = data.MgoFindTotal(data.StockList, filter)
|
|
md.Data, _ = data.MgoFindProjection(data.StockList, filter, projection, sort, 0)
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, md, "ok"))
|
|
}
|
|
|
|
func StockInfoMon(c *gin.Context) {
|
|
param := model.StockMonRes{}
|
|
err := c.BindJSON(¶m)
|
|
fmt.Println(param)
|
|
if err != nil {
|
|
applogger.Error("BindJSON", err.Error())
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "param error", internal.QueryError))
|
|
return
|
|
} else if len(param.Result) <= 0 {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "param null", internal.QueryError))
|
|
return
|
|
} else if param.Token != Token {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "token error", internal.QueryError))
|
|
return
|
|
} else if param.Country == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "country error", internal.QueryError))
|
|
return
|
|
} else if param.Status == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "status error", internal.QueryError))
|
|
return
|
|
}
|
|
var dataList []mongo.WriteModel
|
|
for _, v := range param.Result {
|
|
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.String()},
|
|
{"high_price", v.HighPrice.String()},
|
|
{"low_price", v.LowPrice.String()},
|
|
{"close_price", v.ClosePrice.String()},
|
|
{"desc", v.Desc},
|
|
{"price_code", v.PriceCode},
|
|
{"country", v.Country},
|
|
{"vol", v.Vol},
|
|
{"timestamp", v.Ts},
|
|
}}}
|
|
models := mongo.NewUpdateOneModel().SetFilter(filter).SetUpdate(update).SetUpsert(true)
|
|
dataList = append(dataList, models)
|
|
}
|
|
if err := data.MgoBulkWrite(data.GetStockSouthAsiaTableName(common.CapitalizeFirstLetter(param.Country), param.Status), dataList); err != nil {
|
|
applogger.Error("stock MgoInsertMany err:%v", err)
|
|
}
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, "", "ok"))
|
|
}
|
|
|
|
func StockKLineList(c *gin.Context) {
|
|
symbol := internal.ReplaceStr(c.Query("symbol"))
|
|
country := internal.ReplaceStr(c.Query("country"))
|
|
from := internal.IntegerInit(internal.ReplaceStr(c.Query("from"))) // 开始时间
|
|
to := internal.IntegerInit(internal.ReplaceStr(c.Query("to"))) // 结束时间
|
|
period := internal.ReplaceStr(c.Query("period")) // 时间颗粒度
|
|
size := internal.IntegerInit(internal.ReplaceStr(c.Query("size"))) // 结束时间
|
|
if period == "60min" {
|
|
period = "1hour"
|
|
}
|
|
if symbol == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "symbol error", internal.QueryError))
|
|
return
|
|
} else if period == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "period error", internal.QueryError))
|
|
return
|
|
}
|
|
filter := bson.M{"symbol": symbol, "timestamp": bson.M{"$gte": from, "$lte": to}}
|
|
if size > 0 {
|
|
filter = bson.M{"symbol": symbol}
|
|
}
|
|
tableName := data.GetStockSouthAsiaTableName(common.CapitalizeFirstLetter(country), period)
|
|
|
|
pagedData, err := data.MgoFinds(tableName, filter, int64(size))
|
|
if err != nil {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, err, internal.QueryError))
|
|
return
|
|
}
|
|
var md stock.MgoPageSize
|
|
md.Data = pagedData
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, md, internal.QuerySuccess))
|
|
}
|
|
|
|
func StockKLineUsList(c *gin.Context) {
|
|
symbol := internal.ReplaceStr(c.Query("symbol"))
|
|
from := internal.IntegerInit(internal.ReplaceStr(c.Query("from"))) // 开始时间
|
|
to := internal.IntegerInit(internal.ReplaceStr(c.Query("to"))) // 结束时间
|
|
period := internal.ReplaceStr(c.Query("period")) // 时间颗粒度
|
|
size := internal.IntegerInit(internal.ReplaceStr(c.Query("size"))) // 结束时间
|
|
if period == "60min" {
|
|
period = "1hour"
|
|
}
|
|
if symbol == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "symbol error", internal.QueryError))
|
|
return
|
|
} else if period == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "period error", internal.QueryError))
|
|
return
|
|
}
|
|
filter := bson.M{"code": symbol, "timestamp": bson.M{"$gte": from, "$lte": to}}
|
|
if size > 0 {
|
|
filter = bson.M{"code": symbol}
|
|
}
|
|
tableName := data.GetStockUsTableName(period)
|
|
|
|
pagedData, err := data.MgoFinds(tableName, filter, int64(size))
|
|
if err != nil {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, err, internal.QueryError))
|
|
return
|
|
}
|
|
var md stock.MgoPageSize
|
|
md.Data = pagedData
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, md, internal.QuerySuccess))
|
|
}
|
|
|
|
func StockNewAdd(c *gin.Context) {
|
|
param := model.StockNewsRes{}
|
|
err := c.BindJSON(¶m)
|
|
if err != nil {
|
|
applogger.Error("BindJSON", err.Error())
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "param error", internal.QueryError))
|
|
return
|
|
} else if len(param.Result) <= 0 {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "param null", internal.QueryError))
|
|
return
|
|
} else if param.Token != Token {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "token error", internal.QueryError))
|
|
return
|
|
} else if param.Country == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "country error", internal.QueryError))
|
|
return
|
|
}
|
|
var bsonEod []interface{}
|
|
for _, v := range param.Result {
|
|
bsonEod = append(bsonEod, bson.D{
|
|
{"country", v.Country},
|
|
{"pubdate", v.Pubdate},
|
|
{"title", v.Title},
|
|
{"link", v.Link},
|
|
{"source", v.Source},
|
|
{"code", common.TimeToNow()},
|
|
})
|
|
}
|
|
if len(bsonEod) > 0 {
|
|
if err := data.MgoInsertMany(data.StockNews, bsonEod); err != nil {
|
|
applogger.Error("MgoInsertMany info err: %v", err)
|
|
return
|
|
}
|
|
}
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, "", "ok"))
|
|
}
|
|
|
|
func StockNewsList(c *gin.Context) {
|
|
country := internal.ReplaceStr(c.Query("country"))
|
|
size := internal.IntegerInit(internal.ReplaceStr(c.Query("size")))
|
|
if country == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "country error", internal.QueryError))
|
|
return
|
|
}
|
|
switch country {
|
|
case "Forex":
|
|
country = country
|
|
case "Encryption":
|
|
country = country
|
|
case "UK":
|
|
country = country
|
|
default:
|
|
country = strings.ToLower(country)
|
|
}
|
|
if size == 0 {
|
|
size = TotalSize
|
|
}
|
|
var filter = bson.M{}
|
|
if country != "" {
|
|
filter = bson.M{"country": country}
|
|
}
|
|
applogger.Debug("StockNewsList filter: %v", filter)
|
|
pagedData, err := data.MgoFindsCode(data.StockNews, filter, int64(size))
|
|
if err != nil {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, err, internal.QueryError))
|
|
return
|
|
}
|
|
var md stock.MgoPageSize
|
|
md.Data = pagedData
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, md, internal.QuerySuccess))
|
|
}
|
|
|
|
func StockSouthAsiaInfo(c *gin.Context) {
|
|
symbol := internal.ReplaceStr(c.Query("symbol"))
|
|
country := internal.ReplaceStr(c.Query("country"))
|
|
if symbol == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "symbol error", internal.QueryError))
|
|
return
|
|
} else if country == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "country error", internal.QueryError))
|
|
return
|
|
}
|
|
country = common.CapitalizeFirstLetter(country)
|
|
var pageData = model.StockMogoParam{}
|
|
filter := bson.M{"symbol": symbol}
|
|
res, _ := data.MgoFinds(data.GetStockSouthAsiaTableName(country, "1day"), filter, int64(1))
|
|
pageData.StockCode = symbol
|
|
if len(res) > 0 {
|
|
pageData.HighPrice = business.TypeCheck(res[0]["high_price"])
|
|
pageData.LowPrice = business.TypeCheck(res[0]["low_price"])
|
|
pageData.Vol = res[0]["vol"]
|
|
pageData.PriceTotal = business.TypeCheck(res[0]["price_total"])
|
|
pageData.TurnoverPriceTotal = business.TypeCheck(res[0]["turnover_price_total"])
|
|
}
|
|
pageData.OpenPrice, _ = red.Hget(business.StockClosingPrice[country], symbol)
|
|
pageData.ClosePrice, _ = red.Hget(business.StockClosingPrice[fmt.Sprintf("%sNew", country)], symbol)
|
|
if pageData.ClosePrice == "" || pageData.ClosePrice == "0" { //闭盘期间
|
|
pageData.ClosePrice = pageData.OpenPrice
|
|
pageData.OpenPrice, _ = red.Hget(business.StockClosingPrice[fmt.Sprintf("%sBeforeClose", country)], symbol)
|
|
}
|
|
//if country == "India" {
|
|
filter = bson.M{"Country": country, "Code": symbol}
|
|
projection := bson.M{"Exchange": 1, "Symbol": 1, "NumericCode": 1}
|
|
sort := bson.M{}
|
|
result, _ := data.MgoFindProjection(data.StockList, filter, projection, sort, 0)
|
|
if len(result) > 0 {
|
|
pageData.PrimaryExchange = business.TypeCheck(result[0]["Exchange"])
|
|
pageData.Symbol = business.TypeCheck(result[0]["Symbol"])
|
|
pageData.NumericCode = business.TypeCheck(result[0]["NumericCode"])
|
|
}
|
|
// }
|
|
var md stock.MgoPageSize
|
|
md.Data = pageData
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, md, internal.QuerySuccess))
|
|
}
|
|
|
|
func StockUsInfo(c *gin.Context) {
|
|
symbol := internal.ReplaceStr(c.Query("symbol"))
|
|
if symbol == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "symbol error", internal.QueryError))
|
|
return
|
|
}
|
|
var pageData = model.StockMogoParam{}
|
|
res := business.GetFinnhubBeforClose(symbol)
|
|
if res.C.GreaterThan(decimal.Zero) {
|
|
pageData.OpenPrice = res.O.String()
|
|
pageData.HighPrice = res.H.String()
|
|
pageData.LowPrice = res.L.String()
|
|
pageData.ClosePrice = res.C.String()
|
|
//pageData.Vol = res.Results[0].V.String()
|
|
//pageData.Vw = res.Results[0].VW.String()
|
|
pageData.Symbol = symbol
|
|
}
|
|
filter := bson.M{"Country": "US", "Code": symbol}
|
|
projection := bson.M{"Exchange": 1}
|
|
usData, _ := data.MgoFindProjection(data.StockList, filter, projection, bson.M{}, 1)
|
|
if len(usData) > 0 {
|
|
pageData.PrimaryExchange = usData[0]["Exchange"].(string)
|
|
}
|
|
pageData.PreviousPrice, _ = red.Hget(business.StockClosingPrice[fmt.Sprintf("US")], symbol)
|
|
pageData.ClosePrice, _ = red.Hget(business.StockClosingPrice[fmt.Sprintf("USNew")], symbol) //市价
|
|
if pageData.ClosePrice == "" || pageData.ClosePrice == "0" { //闭盘期间
|
|
pageData.ClosePrice = pageData.PreviousPrice
|
|
pageData.PreviousPrice, _ = red.Hget(business.StockClosingPrice[fmt.Sprintf("USBeforeClose")], symbol)
|
|
}
|
|
|
|
var md stock.MgoPageSize
|
|
md.Data = pageData
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, md, internal.QuerySuccess))
|
|
}
|
|
|
|
func getCodePrice(code, country string) (string, string) {
|
|
if country != "US" {
|
|
return "", ""
|
|
}
|
|
eodModel, _ := business.PreviousClose(code)
|
|
if len(eodModel.Results) <= 0 {
|
|
return "", ""
|
|
}
|
|
dateStrs := common.ConvertToTimezones(eodModel.Results[0].T)
|
|
yesterday := dateStrs
|
|
var i int
|
|
Loop:
|
|
yesterday = yesterday.AddDate(0, 0, -1)
|
|
yesterdayClose, _ := business.UsData(code, yesterday.Format("2006-01-02"))
|
|
if yesterdayClose == "" {
|
|
if i <= 2 {
|
|
time.Sleep(1 * time.Second)
|
|
i++
|
|
goto Loop
|
|
}
|
|
}
|
|
if yesterdayClose == "" {
|
|
return "", ""
|
|
}
|
|
return eodModel.Results[0].C.String(), yesterdayClose
|
|
}
|
|
|
|
func StockListUpdateToPHP(c *gin.Context) {
|
|
param := stock.StockUpdatePolygon{}
|
|
err := c.BindJSON(¶m)
|
|
fmt.Printf("%+v", param)
|
|
if err != nil {
|
|
applogger.Error("BindJSON", err.Error())
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "param error", internal.QueryError))
|
|
return
|
|
} else if param.NewCode == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "new ticker error", internal.QueryError))
|
|
return
|
|
} else if param.Locale == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "locale error", internal.QueryError))
|
|
return
|
|
} else if param.Token != Token {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "token error", internal.QueryError))
|
|
return
|
|
} else if param.Source == 0 {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "source error", internal.QueryError))
|
|
return
|
|
}
|
|
param.Locale = common.CapitalizeFirstLetter(param.Locale)
|
|
filter := bson.M{"Code": param.NewCode,
|
|
"Country": param.Locale,
|
|
}
|
|
updateData := bson.D{{"$set", bson.D{
|
|
{"Source", param.Source}}}}
|
|
if err := data.MgoUpdateOne(data.StockList, filter, updateData); err != nil {
|
|
applogger.Error("php update err:%v", err)
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "operation failure", internal.QueryError))
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, "", "ok"))
|
|
}
|
|
|
|
func StockListAddToPHP(c *gin.Context) {
|
|
param := stock.StockUpdatePolygon{}
|
|
err := c.BindJSON(¶m)
|
|
fmt.Printf("%+v", param)
|
|
if err != nil {
|
|
applogger.Error("BindJSON", err.Error())
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "param error", internal.QueryError))
|
|
return
|
|
} else if param.NewCode == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "new ticker error", internal.QueryError))
|
|
return
|
|
} else if param.OldCode == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "old ticker error", internal.QueryError))
|
|
return
|
|
} else if param.Locale == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "locale error", internal.QueryError))
|
|
return
|
|
} else if param.Token != Token {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "token error", internal.QueryError))
|
|
return
|
|
} else if param.PrimaryExchange == "" {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "primary exchange error", internal.QueryError))
|
|
return
|
|
}
|
|
//转换股票code类型
|
|
param.Locale = common.CapitalizeFirstLetter(param.Locale)
|
|
param.OldCode = common.GetNewCode(param.PrimaryExchange, param.OldCode, param.Locale)
|
|
param.NewCode = common.GetNewCode(param.PrimaryExchange, param.NewCode, param.Locale)
|
|
var dataList []mongo.WriteModel
|
|
filter := bson.M{"Code": param.OldCode,
|
|
"Country": param.Locale,
|
|
}
|
|
yesterdayClose, beforeClose := getCodePrice(param.OldCode, param.Locale)
|
|
if yesterdayClose != "" {
|
|
param.YesterdayClose = yesterdayClose
|
|
} else {
|
|
beforeClose = param.YesterdayClose
|
|
}
|
|
updateData := bson.M{}
|
|
updateData["Code"] = param.NewCode
|
|
updateData["Country"] = param.Locale
|
|
if param.Name != "" {
|
|
updateData["Name"] = param.Name
|
|
}
|
|
if param.NumericCode != "" {
|
|
updateData["NumericCode"] = param.NumericCode
|
|
}
|
|
if param.PrimaryExchange != "" {
|
|
updateData["Exchange"] = param.PrimaryExchange
|
|
updateData["Tape"] = TapsMap[strings.ReplaceAll(param.PrimaryExchange, " ", "")]
|
|
}
|
|
if param.YesterdayClose != "" {
|
|
updateData["YesterdayClose"] = param.YesterdayClose
|
|
}
|
|
if beforeClose != "" {
|
|
updateData["BeforeClose"] = beforeClose
|
|
}
|
|
if param.IsReal != 0 {
|
|
updateData["IsReal"] = param.IsReal
|
|
}
|
|
if param.Intro != "" {
|
|
updateData["Intro"] = param.Intro
|
|
}
|
|
if param.Currency != "" {
|
|
updateData["Currency"] = param.Currency
|
|
}
|
|
if param.Source != 0 {
|
|
updateData["Source"] = param.Source
|
|
}
|
|
updateData["Symbol"] = common.GetOldCode(param.NewCode)
|
|
update := bson.M{"$set": updateData}
|
|
//修改股票CODE
|
|
if param.OldCode != param.NewCode {
|
|
//判断修改原数据是否存在
|
|
total, _ := data.MgoFindTotal(data.StockList, filter)
|
|
if total == 0 {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "stock code not exist", internal.QueryError))
|
|
return
|
|
}
|
|
if param.Locale != "US" {
|
|
go func(param stock.StockUpdatePolygon) {
|
|
for _, v := range dictionary.StockSouthAsiaListTime {
|
|
tableName := data.GetStockSouthAsiaTableName(param.Locale, v)
|
|
if err := data.MgoUpdateMany(tableName, bson.D{{"symbol", bson.M{
|
|
"$eq": param.OldCode,
|
|
}}}, bson.D{{"$set", bson.D{
|
|
{"stock_code", common.GetOldCode(param.NewCode)},
|
|
{"symbol", param.NewCode}}}}); err != nil {
|
|
applogger.Error("Mgo update Many err:%v", err)
|
|
}
|
|
}
|
|
}(param)
|
|
}
|
|
param.YesterdayClose, _ = red.Hget(business.StockClosingPrice[param.Locale], param.OldCode)
|
|
beforeClose, _ = red.Hget(business.StockClosingPrice[fmt.Sprintf("%sBeforeClose", param.Locale)], param.OldCode)
|
|
}
|
|
models := mongo.NewUpdateOneModel().SetFilter(filter).SetUpdate(update).SetUpsert(true)
|
|
dataList = append(dataList, models)
|
|
red.Hset(business.StockClosingPrice[param.Locale], param.NewCode, param.YesterdayClose)
|
|
red.Hset(business.StockClosingPrice[fmt.Sprintf("%sBeforeClose", param.Locale)], param.NewCode, beforeClose)
|
|
red.Hset(business.StockClosingPrice[fmt.Sprintf("%sNew", param.Locale)], param.NewCode, "0")
|
|
if len(dataList) > 0 {
|
|
if err := data.MgoBulkWrite(data.StockList, dataList); err != nil {
|
|
applogger.Error("MgoInsertMany err:%v", err)
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "operation failure", internal.QueryError))
|
|
return
|
|
}
|
|
} else {
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "error operation repetition", internal.QueryError))
|
|
return
|
|
}
|
|
|
|
// 新增美股行情分发股票代码列表
|
|
WriteShareUs(param.NewCode)
|
|
|
|
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, "", "ok"))
|
|
}
|
|
|
|
// WriteShareUs
|
|
//
|
|
// @Description: 新增美股行情分发股票代码列表
|
|
// @param code
|
|
func WriteShareUs(code string) {
|
|
url := fmt.Sprintf("http://%v/usWss/add/code?code=%v", config.Config.FinnhubUs.DispenseWss, code)
|
|
applogger.Debug("url data info:%v", url)
|
|
|
|
bodyStr, err := internal.HttpGet(url)
|
|
if err != nil {
|
|
applogger.Error("WriteShareUs err info:%v", err)
|
|
return
|
|
}
|
|
applogger.Debug("new add shareUs code info:%v", bodyStr)
|
|
}
|
|
|