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.

350 lines
12 KiB

package processor
import (
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"net/http"
"strings"
"wss-pool/cmd/common"
"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"
)
func OptionInfoAdd(c *gin.Context) {
param := make([]model.OptionInfoParam, 0)
err := c.BindJSON(&param)
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
} else if param[0].CloseDate != common.TimeToNows().Format("2006-01-02") {
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "option date not today ", internal.QueryError))
return
}
country := common.CapitalizeFirstLetter(param[0].Country)
if country == "Us" {
country = "US"
}
var dataList []mongo.WriteModel
applogger.Debug("stock info add param total: %d", total)
for _, v := range param {
red.HsetMap(business.StockClosingPrice[fmt.Sprintf("Option%sNew", country)], v.Stock, v.FutPrice)
//爬虫抓取列表数据 延迟较大 统一用info 数据
business.StockPyWsOptionList(model.OptionPolygon{
Stock: v.Stock,
Percent: v.Percent,
FutPrice: v.FutPrice,
Country: country,
}, fmt.Sprintf("%s%s%s", common.StockOption, country, common.StockOptionList))
filter := bson.M{"code": bson.M{"$eq": v.Stock}}
update := bson.D{{"$set", bson.D{
{"code", v.Stock},
{"fut_price", v.FutPrice},
{"percent", v.Percent},
{"atmiv", v.ATMIV},
{"ivp", v.IVP},
{"option_date", v.CloseDate},
{"country", v.Country},
}}}
code := fmt.Sprintf("%s:%s", business.StockClosingPrice[fmt.Sprintf("Option%sPrice", country)], v.Stock)
strike := make(map[string]string)
for key, val := range v.Results {
//标的名+到期时间+行权价+类型
for key2, val2 := range val {
title := fmt.Sprintf("%s%s%s", v.Stock, strings.Replace(key, "-", "", -1), val2.Strike)
val[key2].Calls.Name = title + "CE"
business.OptionResPrice(model.StrikePrice{
Ask: val2.Calls.OfferOff,
Bid: val2.Calls.BidOff,
Price: val2.Calls.LTPOff,
Code: v.Stock,
}, val[key2].Calls.Name, code, v.IsClose, v.CloseDate, key)
val[key2].Puts.Name = title + "PE"
business.OptionResPrice(model.StrikePrice{
Ask: val2.Puts.OfferOff,
Bid: val2.Puts.BidOff,
Price: val2.Puts.LTPOff,
Code: v.Stock,
}, val[key2].Puts.Name, code, v.IsClose, v.CloseDate, key)
if val2.IsDefault {
strike[key] = val2.Strike
// break
}
}
val = common.QuickSort(val)
//fmt.Printf("%v",val)
//分开写入mogodb
filterExpiry := bson.M{"code": v.Stock, "expiry": key}
info, _ := json.Marshal(val)
expiryDate, _ := common.TimeStrToTimestamp(fmt.Sprintf("%s 23:59:59", key))
updateExpiry := bson.D{{"$set", bson.D{
{"code", v.Stock},
{"expiry", key},
{"expiry_date", expiryDate},
{"info", string(info)},
}}}
if err := data.MgoUpdateOneTrue(data.GetOptionExpiryTableName(country), filterExpiry, updateExpiry); err != nil {
applogger.Error("%s MgoInsertMany err:%v", v.Stock, err)
}
}
business.StockPyWsOptionInfo(v, fmt.Sprintf("%s%s%s", common.StockOption, country, common.StockOptionInfo))
business.StockPyWsOptionInfoExchange(model.OptionInfoExchange{
Country: v.Country,
Stock: v.Stock,
FutPrice: v.FutPrice,
Percent: v.Percent,
Strike: strike,
}, fmt.Sprintf("%s%s%s.%s", common.StockOption, country, common.StockOptionInfo, "Exchange"))
models := mongo.NewUpdateOneModel().SetFilter(filter).SetUpdate(update).SetUpsert(true)
dataList = append(dataList, models)
}
if len(dataList) > 0 {
if err := data.MgoBulkWrite(data.GetOptionTableName(country), dataList); err != nil {
applogger.Error("stock MgoInsertMany err:%v", err)
}
}
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, "", "ok"))
}
func OptionListAdd(c *gin.Context) {
param := model.OptionIndexList{}
err := c.BindJSON(&param)
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].Stock == "" {
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "ticker error", internal.QueryError))
return
} else if param.Results[0].Country == "" {
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "locale error", internal.QueryError))
return
}
locale := common.CapitalizeFirstLetter(param.Results[0].Country)
closeDate := common.TimeToNows().Format("2006-01-02")
if locale == "Us" {
locale = "US"
}
var dataList []mongo.WriteModel
for _, value := range param.Results {
if closeDate != strings.TrimSpace(value.CloseDate) {
continue
}
filter := bson.D{{"Code", bson.M{
"$eq": value.Stock,
}}, {"Country", bson.M{
"$eq": locale,
}}}
update := bson.D{{"$set", bson.D{
{"Code", value.Stock},
{"Country", locale},
{"FutPrice", value.FutPrice},
{"Percent", value.Percent},
{"IVChg", value.IVChg},
{"IVP", value.IVP},
{"Exchange", value.PrimaryExchange},
{"DateTime", closeDate},
{"ATMIV", value.ATMIV}}}}
if value.IsClose {
red.HsetMap(business.StockClosingPrice[fmt.Sprintf("Option%sNew", locale)], value.Stock, "0")
red.HsetMap(business.StockClosingPrice[locale], value.Stock, value.FutPrice)
list, _ := data.MgoFind(data.OptionList, bson.M{"Country": locale, "Code": value.Stock, "CloseDate": bson.M{"$ne": closeDate}})
lists := list.([]primitive.M)
if len(lists) > 0 {
beforeClose, ok := lists[0]["YesterdayClose"].(string)
if ok {
red.HsetMap(business.StockClosingPrice[fmt.Sprintf("Option%sBeforeClose", locale)], value.Stock, beforeClose)
}
update = bson.D{{"$set", bson.D{
{"Code", value.Stock},
{"Country", locale},
{"FutPrice", value.FutPrice},
{"Percent", value.Percent},
{"IVChg", value.IVChg},
{"IVP", value.IVP},
{"Exchange", value.PrimaryExchange},
{"DateTime", closeDate},
{"YesterdayClose", value.FutPrice}, //上一次 闭盘价
{"BeforeClose", beforeClose}, //前一天
{"CloseDate", closeDate},
{"ATMIV", value.ATMIV}}}}
} else {
update = bson.D{{"$set", bson.D{
{"Code", value.Stock},
{"Country", locale},
{"FutPrice", value.FutPrice},
{"Percent", value.Percent},
{"IVChg", value.IVChg},
{"IVP", value.IVP},
{"Exchange", value.PrimaryExchange},
{"DateTime", closeDate},
{"YesterdayClose", value.FutPrice}, //上一次 闭盘价
{"CloseDate", closeDate},
{"ATMIV", value.ATMIV}}}}
}
}
models := mongo.NewUpdateOneModel().SetFilter(filter).SetUpdate(update).SetUpsert(true)
dataList = append(dataList, models)
}
//标记 批量少于 3 不做修改
if len(dataList) >= 3 {
data.MgoUpdateMany(data.OptionList, bson.D{{"Country", bson.M{
"$eq": locale,
}}, {"DateTime", bson.M{
"$ne": "0",
}}}, bson.D{{"$set", bson.D{
{"DateTime", "0"}}}})
}
if len(dataList) > 0 {
data.MgoBulkWrite(data.OptionList, dataList)
if err := data.MgoBulkWrite(data.OptionList, 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
}
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, "", "ok"))
}
func ExchangeOptionList(c *gin.Context) {
country := internal.ReplaceStr(c.Query("country"))
pageSize := internal.IntegerInit(internal.ReplaceStr(c.Query("pageSize")))
pageNumber := internal.IntegerInit(internal.ReplaceStr(c.Query("pageNumber")))
sort := internal.IntegerInit(internal.ReplaceStr(c.Query("sort")))
search := internal.ReplaceStr(c.Query("search"))
code := internal.ReplaceStr(c.Query("code"))
if pageSize <= 0 || pageNumber <= 0 {
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "分页参数不能为零", internal.QueryError))
return
}
var condition = country
var filter bson.M
if len(search) > 0 {
if len(condition) > 0 {
filter = bson.M{"Country": condition, "DateTime": bson.M{"$ne": "0"}, "$or": []bson.M{{"Code": bson.M{"$regex": search}}}}
} else {
filter = bson.M{"$or": []bson.M{{"Code": bson.M{"$regex": search}}}, "DateTime": bson.M{"$ne": "0"}}
}
} else {
filter = bson.M{"Country": condition, "DateTime": bson.M{"$ne": "0"}}
}
strs := strings.Split(code, "-")
if len(code) > 0 {
filter = bson.M{"Country": condition, "DateTime": bson.M{"$ne": "0"}, "Code": bson.M{"$in": strs}}
}
//fmt.Println(filter)
total, err := data.MgoFindTotal(data.OptionList, filter)
if err != nil {
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, err, internal.QueryError))
return
}
//applogger.Debug("查询数据总数: %v", total)
pageData := make([]model.OptionPolygon, 0)
if sort == 0 {
sort = -1
}
data.MgoPagingFindStructList(data.OptionList, filter, int64(pageSize), int64(pageNumber), "Percent", sort, &pageData)
var md stock.MgoPageSize
md.PageSize = pageSize
md.PageNumber = pageNumber
md.Total = total
if len(pageData) <= 0 {
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, md, internal.QuerySuccess))
return
}
data := make([]model.OptionPolygon, 0)
for k, v := range pageData {
if ok, rate := common.IsExistOption(v.Country, v.Stock); ok {
pageData[k].Rate = rate
data = append(data, pageData[k])
}
}
md.Data = data
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, md, internal.QuerySuccess))
}
func OptionPHPList(c *gin.Context) {
country := internal.ReplaceStr(c.Query("country"))
var condition = country
filter := bson.M{"Country": condition, "DateTime": bson.M{"$ne": "0"}}
result, _ := data.MgoFind(data.OptionList, filter)
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, result, internal.QuerySuccess))
}
func OptionInfo(c *gin.Context) {
code := internal.ReplaceStr(c.Query("option"))
country := internal.ReplaceStr(c.Query("country"))
if code == "" {
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "option error", internal.QueryError))
return
} else if country == "" {
c.JSON(http.StatusOK, internal.GinResult(http.StatusBadRequest, "country error", internal.QueryError))
return
}
country = common.CapitalizeFirstLetter(country)
fmt.Println(common.TimeToNow())
var res = make([]model.OptionInfoMogo, 1)
filter := bson.M{"code": code}
data.MgoFindToStr(data.GetOptionTableName(country), filter, int64(1), &res)
strikeMap := make(map[string][]model.StrikeInfo)
if len(res) <= 0 {
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, model.OptionInfoParam{}, internal.QuerySuccess))
return
}
filter = bson.M{"code": code, "expiry_date": bson.M{
"$gte": common.TimeToNow(),
}}
info := make([]model.OptionInfoExpiryMogo, 0)
data.MgoFindToStr(data.GetOptionExpiryTableName(country), filter, int64(0), &info)
if len(info) <= 0 {
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, model.OptionInfoParam{}, internal.QuerySuccess))
return
}
for _, v := range info {
item := make([]model.StrikeInfo, 0)
json.Unmarshal([]byte(v.Info), &item)
strikeMap[v.Expiry] = item
}
var pageData = model.OptionInfoParam{
Country: res[0].Country,
Stock: res[0].Stock,
FutPrice: res[0].FutPrice,
Percent: res[0].Percent,
IVP: res[0].IVP,
ATMIV: res[0].ATMIV,
Results: strikeMap,
}
c.JSON(http.StatusOK, internal.GinResult(http.StatusOK, pageData, internal.QuerySuccess))
}