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(¶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 } 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(¶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].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)) }