package data import ( "context" "encoding/json" "github.com/go-xorm/xorm" "github.com/shopspring/decimal" "matchmaking-system/internal/biz/structure" "matchmaking-system/internal/data/tradedeal/virtual" "matchmaking-system/internal/pkg/flags" "matchmaking-system/internal/pkg/logging/applogger" "matchmaking-system/internal/pkg/logging/common" "matchmaking-system/internal/pkg/setting" "matchmaking-system/internal/pkg/utils" "strings" orders "matchmaking-system/internal/data/convert" forexd "matchmaking-system/internal/data/tradedeal/forex" models "matchmaking-system/internal/pkg/model" ) // GetBotForexTradeList // // @Description: 外汇订单列表查询 // @receiver uo // @param ctx // @param pageSize // @param pageCount // @param userId // @param status // @return []*models.BotForexTrade // @return int64 // @return error func (uo *userOrderRepo) GetBotForexTradeList(ctx context.Context, pageSize, pageCount, userId, status int64) ([]*models.BotForexTrade, int64, error) { totalCount, err := uo.data.mysqlDB.Table(flags.BotForexTrade). Where("user_id = ?", userId). Where("status = ?", status). Count() if err != nil { return nil, 0, flags.ErrMySqlDB } if totalCount == 0 { return nil, 0, nil } var contractList []*models.BotForexTrade if err = uo.data.mysqlDB.Table(flags.BotForexTrade). Where("user_id = ?", userId). Where("status = ?", status). Limit(int(pageSize), int(pageCount)). Desc(GetOrderByStatusSort(status)). Find(&contractList); err != nil { return nil, 0, flags.ErrMySqlDB } var contractUpdateList []*models.BotForexTrade for _, value := range contractList { value.KeepDecimal = GetKeepDecimal(flags.ForexSystemSetUpKey, value.ContractId) contractUpdateList = append(contractUpdateList, value) } return contractUpdateList, totalCount, nil } // CreateBotForexTrade // // @Description: 外汇下单 // @receiver uo // @param ctx // @param userId // @param order // @return string // @return error func (uo *userOrderRepo) CreateBotForexTrade(ctx context.Context, userId int64, order structure.ForexOrder) (string, error) { // 1、外汇下单订阅 forexId := strings.ToUpper(order.ForexId) _, ok := forexWh.ForexMapSymbol.Load(forexId) if ok { go func() { forexWh.ForexMap <- []byte(forexId) }() } // 2、获取系统设置 system, err := GetForexSystemSetUp(forexId) if err != nil || system == nil { return flags.SetNull, flags.ErrContractOne } order.System = system // TODO: 3、获取外汇交易对的买一卖一价格 //priceNew, err := GetDigitalCurrencyForexPrice(ctx, flags.Wh, forexId, order.TradeType) //if len(priceNew) == 0 || err != nil { // applogger.Error("%v CreateBotForexTrade.ForexSubMarketPrice:%v", common.ErrForex, err) // return flags.SetNull, flags.ErrPriceUpdate //} // 4、外汇下单判定 // TODO: 杠杆校验 //pryNum := decimal.RequireFromString(order.PryNum) //if pryNum.Cmp(order.System.MinPry) < 0 || pryNum.Cmp(order.System.MaxPry) > 0 { // return flags.SetNull, flags.ErrContractTow //} // 下单判定设置(false无设置|true止盈止损) checkBool, stopWinPrice, stopLossPrice, err := ForexVoteStopType(order) if err != nil { applogger.Error("%v CreateBotForexTrade.ForexVoteStopType:%v", common.ErrForex, err) return flags.SetNull, err } // 下单判定设置(限价|市价) limitOrMarketPrice, err := uo.ForexVoteDealType(order) if err != nil { applogger.Error("%v CreateBotForexTrade.ForexVoteDealType:%v", common.ErrForex, err) return flags.SetNull, err } // 下单判定设置(买涨|买跌) if err = uo.ForexVoteTradeType(order.TradeType, stopWinPrice, stopLossPrice, limitOrMarketPrice, checkBool); err != nil { applogger.Error("%v CreateBotForexTrade.ForexVoteTradeType:%v", common.ErrForex, err) return flags.SetNull, err } // 5、外汇下单(订单信息|资产信息) orderId, err := uo.ForexOrdersWriteDB(ctx, userId, order) if err != nil || len(orderId) == 0 { applogger.Error("%v CreateBotForexTrade.ForexOrdersWriteDB:%v", common.ErrForex, err) return flags.SetNull, err } // 6、写入缓存列表(挂单缓存|持仓缓存),等待撮合计算 marketStatus, tallyCache, err := forexd.ForexCacheDeal(ctx, userId, orderId, limitOrMarketPrice.String(), order) if err != nil || tallyCache == nil { applogger.Error("%v CreateBotForexTrade.ForexCacheDeal:%v", common.ErrForex, err) return flags.SetNull, err } // 7、市价下单开仓处理(订单信息|资产信息|手续费|返佣|资产详情记录) if marketStatus == setting.MarketForexPosition { if err = ForexOpenPosition(ctx, uo.data.mysqlDB, userId, orderId, tallyCache.OpenPrice, order); err != nil { applogger.Error("%v CreateBotForexTrade.ForexOpenPosition:%v", common.ErrForex, err) return flags.SetNull, err } } // 8、写入(挂单|持仓)缓存列表 if err = forexd.ForexPushAddCache(Reds, marketStatus, tallyCache); err != nil { applogger.Error("%v CreateBotForexTrade.ForexPushAddCache:%v", common.ErrForex, err) return flags.SetNull, flags.ErrCacheDB } // 9、写入用户订单订阅缓存列表 orderIdKey := virtual.OrderIdListKey(setting.ForexSubscribe, userId) if err = forexd.ForexHashSetOrderId(Reds, orderIdKey, tallyCache); err != nil { applogger.Error("%v CreateBotForexTrade.ForexPushAddOrder:%v", common.ErrForex, err) return flags.SetNull, flags.ErrCacheDB } // 10、写入管理员订单订阅缓存列表 if err = forexd.ForexHashSetOrderId(Reds, setting.AdminForexSubscribe, tallyCache); err != nil { applogger.Error("%v CreateBotForexTrade.ForexHashSetOrderId:%v", common.ErrForex, err) return flags.SetNull, flags.ErrCacheDB } return orderId, nil } // ForexOrdersWriteDB // // @Description: 外汇下单处理 // @receiver uo // @param ctx // @param userId // @param order // @return string // @return error func (uo *userOrderRepo) ForexOrdersWriteDB(ctx context.Context, userId int64, order structure.ForexOrder) (string, error) { session := uo.data.mysqlDB.NewSession() defer session.Close() err := session.Begin() if err != nil { applogger.Error("%v ForexOrdersWriteDB.NewSession:%v", common.ErrForex, err) return flags.SetNull, flags.ErrMySqlDB } // 查询当前下单用户可用账户金额和冻结金额 var usable, frozen, usableNo, frozenNo decimal.Decimal usable, frozen, _, err = uo.GetBotUserForex(session, userId, flags.ForexUnit) if err != nil { applogger.Error("%v ForexOrdersWriteDB.GetBotUserForex:%v", common.ErrForex, err) return flags.SetNull, flags.ErrMySqlDB } // 检查用户订单下单资产 if usable.IsZero() || usable.IsNegative() || frozen.IsNegative() { return flags.SetNull, flags.ErrPublicOne } // 查询当前下单用户可用非账户和冻结金额 var checkCount int if order.ForexId != flags.ForexUnit { usableNo, frozenNo, checkCount, err = uo.GetBotUserForex(session, userId, order.ForexId) if err != nil { applogger.Error("%v ForexOrdersWriteDB.GetBotUserForex.Fei:%v", common.ErrForex, err) return flags.SetNull, flags.ErrMySqlDB } } if !flags.CheckSetting { applogger.Debug("下单可用金额:%v", usable) applogger.Debug("下单冻结金额:%v", frozen) applogger.Debug("非下单可用金额:%v", usableNo) applogger.Debug("非下单冻结金额:%v", frozenNo) } // 写入订单信息 orderId, err := uo.VerifyBotForexTradeOrderId(session) if err != nil { applogger.Error("%v ForexOrdersWriteDB.VerifyBotForexTradeOrderId:%v", common.ErrForex, err) return flags.SetNull, err } if !flags.CheckSetting { applogger.Debug("下单Id:%v", orderId) applogger.Debug("杠杆:%v", order.PryNum) } // 写入订单表: 保证金 = (手数(1000 / 100000) * 合约单位(100000)) / 杠杆 * 汇率 botStockTrade := orders.BotForexTrade(ctx, userId, orderId, order) if err = uo.CreatBotForexTrade(session, botStockTrade); err != nil { applogger.Error("%v ForexOrdersWriteDB.CreatBotForexTrade:%v", common.ErrForex, err) return flags.SetNull, flags.ErrMySqlDB } // 订单总金额 = 保证金 + 手续费 earnestMoney := decimal.RequireFromString(order.EarnestMoney) // 保证金 serviceCost := decimal.RequireFromString(order.ServiceCost) // 手续费 totalMoney := earnestMoney.Add(serviceCost) // 总金额下单判定 residue := usable.Sub(totalMoney).Div(usable) if usable.Cmp(totalMoney) < 0 || residue.Cmp(utils.DecimalsStrInt()) < 0 { return flags.SetNull, flags.ErrPublicOne } // (买涨|买跌)处理 var usableNew, frozenNew, usableNewNo, frozenNewNo decimal.Decimal usableNew = usable.Sub(totalMoney) // 可用资产 frozenNew = frozen.Add(totalMoney) // 冻结资产 if order.ForexId != flags.ForexUnit { usableNewNo = usableNo // 可用非资产 frozenNewNo = frozenNo // 冻结非资产 } // 检查用户订单下单资产 if usableNew.IsNegative() || usableNew.IsZero() { return flags.SetNull, flags.ErrPublicTow } if !flags.CheckSetting { applogger.Debug("下单后用户可用资产:%v", usableNew) applogger.Debug("下单后用户冻结资产:%v", frozenNew) applogger.Debug("下单后用户非可用资产:%v", usableNewNo) applogger.Debug("下单后用户非冻结资产:%v", frozenNewNo) } // 更新用户资产信息 userForexUSDT := orders.UpdateBotUserForex(ctx, usableNew.String(), frozenNew.String()) if err = uo.UpdateBotUserForex(session, userId, flags.ForexUnit, userForexUSDT); err != nil { applogger.Error("%v ForexOrdersWriteDB.UpdateBotUserForex:%v", common.ErrForex, err) return flags.SetNull, flags.ErrMySqlDB } // 更新非资产信息 if order.ForexId != flags.ForexUnit { if checkCount == 0 { userDigitalSymbol := orders.CreatBotUserForex(ctx, userId, usableNewNo.String(), frozenNewNo.String(), order) err = uo.CreatBotUserForex(session, userDigitalSymbol) if err != nil { applogger.Error("%v ForexOrdersWriteDB.CreatBotUserForex:%v", common.ErrForex, err) return flags.SetNull, flags.ErrMySqlDB } } else { userForex := orders.UpdateBotUserForex(ctx, usableNewNo.String(), frozenNewNo.String()) if err = uo.UpdateBotUserForex(session, userId, order.ForexId, userForex); err != nil { applogger.Error("%v ForexOrdersWriteDB.UpdateBotUserForex:%v", common.ErrForex, err) return flags.SetNull, flags.ErrMySqlDB } } } if err = session.Commit(); err != nil { applogger.Error("%v ForexOrdersWriteDB.Commit:%v", common.ErrForex, err) return flags.SetNull, flags.ErrMySqlDB } return orderId, nil } // ForexOpenPosition // // @Description: 外汇开仓处理 // @param ctx // @param db // @param userId // @param orderId // @param openPrice // @param order // @return error func ForexOpenPosition(ctx context.Context, db *xorm.EngineGroup, userId int64, orderId, openPrice string, order structure.ForexOrder) error { session := db.NewSession() defer session.Close() err := session.Begin() if err != nil { applogger.Error("%v ForexOpenPosition.NewSession:%v", common.ErrForex, err) return flags.ErrMySqlDB } // 查询当前下单用户可用账户金额和冻结金额 var usable, frozen, usableNo, frozenNo decimal.Decimal usable, frozen, _, err = Uo.GetBotUserForex(session, userId, flags.ForexUnit) if err != nil { applogger.Error("%v ForexOpenPosition.GetBotUserForex:%v", common.ErrForex, err) return flags.ErrMySqlDB } if usable.IsNegative() || frozen.IsNegative() { return flags.ErrPublicThree } if !flags.CheckSetting { applogger.Debug("下单可用金额:%v", usable) applogger.Debug("下单冻结金额:%v", frozen) } if order.ForexId != flags.ForexUnit { usableNo, frozenNo, _, err = Uo.GetBotUserForex(session, userId, order.ForexId) if err != nil { applogger.Error("%v ForexOpenPosition.GetBotUserForex:%v", common.ErrForex, err) return flags.ErrMySqlDB } } earnestMoney := decimal.RequireFromString(order.EarnestMoney) // 下单保证金 openOrderNumber := decimal.RequireFromString(order.OrderNumber) // 下单仓位 = 保证金 / (一手保证金 * 杠杆倍数) serviceCost := decimal.RequireFromString(order.ServiceCost) // 下单手续费 totalMoney := earnestMoney.Add(serviceCost) // 下单总金额 = (订单手续费 + 保证金) openFaceValue := order.System.FaceValue // 面值(暂不使用) openOrderPrice := decimal.RequireFromString(openPrice) // 开仓价格(下单金额) pryNum := decimal.RequireFromString(order.PryNum) // 杠杆 if !flags.CheckSetting { applogger.Debug("下单订单杠杆:%v", pryNum) applogger.Debug("下单保证金:%v", earnestMoney) applogger.Debug("下单订单数量:%v", openOrderNumber) applogger.Debug("下单订单手续费:%v", serviceCost) applogger.Debug("下单订单总金额:%v", totalMoney) } // 手续费记录 openPriceNew := openOrderPrice.Mul(openOrderNumber).String() // 开仓手续费 = 开仓价格 * 仓位数 * 手续费比例 cost, err := Uo.CalculateHandlingFees(ctx, session, int(userId), flags.ForexMarketType, flags.OpenBrokType, orderId, openPriceNew, openFaceValue.String()) if err != nil { applogger.Error("%v ForexOpenPosition.CalculateHandlingFees:%v", common.ErrForex, err) return err } openServiceCost := decimal.RequireFromString(cost) // 开仓手续费 openTotalMoney := earnestMoney.Add(openServiceCost) // 开仓总金额 = (保证金 + 开仓手续费) floatPrice := totalMoney.Sub(openTotalMoney) // 计算容差 = 下单总额 - 开仓总额 if !flags.CheckSetting { applogger.Debug("开仓订单价格:%v", openOrderPrice) applogger.Debug("开仓仓位:%v", openOrderNumber) applogger.Debug("开仓手续费:%v", openServiceCost) applogger.Debug("开仓总金额:%v", openTotalMoney) applogger.Debug("下单开仓总金额容差值:%v", floatPrice) } usableNew := usable.Add(floatPrice) // 可用资产(处理容差值) frozenNew := frozen.Sub(totalMoney).Add(earnestMoney) // 冻结资产 = 冻结资产 - 下单冻结资产 + 开仓保证金 usableNoNew := usableNo.Add(openOrderNumber) // 非可用资产 frozenNoNew := frozenNo // 非冻结资产 if !flags.CheckSetting { applogger.Debug("下单后用户可用资产:%v", usableNew) applogger.Debug("下单后用户冻结资产:%v", frozenNew) } applogger.Debug("下单冻结资产:%v", frozen) applogger.Debug("下单后的冻结总资产:%v", totalMoney) applogger.Debug("开仓后的保证金:%v", earnestMoney) applogger.Debug("下单后用户冻结资产:%v", frozenNew) applogger.Debug("下单后用户可用资产:%v", usableNew) // 检查用户平仓资产 if usableNoNew.IsNegative() { return flags.ErrPublicThree } // 处理资产信息 userForexUSDT := orders.UpdateBotUserForex(ctx, usableNew.String(), frozenNew.String()) if err = Uo.UpdateBotUserForex(session, userId, flags.ForexUnit, userForexUSDT); err != nil { applogger.Error("%v ForexOpenPosition.UpdateBotUserForex:%v", common.ErrForex, err) return flags.ErrMySqlDB } // 更新非资产信息 if order.ForexId != flags.ForexUnit { userForex := orders.UpdateBotUserForex(ctx, usableNoNew.String(), frozenNoNew.String()) if err = Uo.UpdateBotUserForex(session, userId, order.ForexId, userForex); err != nil { applogger.Error("%v ForexOpenPosition.UpdateBotUserForex:%v", common.ErrForex, err) return flags.ErrMySqlDB } } // 处理订单信息(成交价|仓位|开仓时间|订单总金额|手续费|持仓状态) trade := orders.UpdateOpenBotForexTrade(ctx, openPrice, openOrderNumber.String(), openTotalMoney.String(), openServiceCost.String()) if err = Uo.UpdateBotForexTradeByOrderId(session, orderId, trade); err != nil { applogger.Error("%v ForexOpenPosition.UpdateBotForexTradeByOrderId:%v", common.ErrForex, err) return flags.ErrMySqlDB } // 返佣记录|资金信息|资金详情信息 if err = Uo.ForexRebateCalculation(ctx, session, int(userId), flags.ForexMarketType, flags.OpenBrokType, flags.OpenMRebate, cost, orderId); err != nil { applogger.Error("%v ForexOpenPosition.ForexRebateCalculation:%v", common.ErrForex, err) return flags.ErrMySqlDB } // 更改交易日志记录方式 var list []models.BotUserForexLog qData0 := orders.CreatBotUserForexLog(ctx, userId, flags.CostMoney, flags.ForexUnit, NegativeValue(openServiceCost.String()), orderId) // 资金变动明细表(开仓手续费) qData1 := orders.CreatBotUserForexLog(ctx, userId, flags.Freeze, flags.ForexUnit, NegativeValue(earnestMoney.String()), orderId) // 资金变动明细表(开仓保证金) qData2 := orders.CreatBotUserForexLog(ctx, userId, flags.ChangeInto, order.ForexId, openOrderNumber.String(), orderId) // 资金变动明细表(非资产) list = append(list, qData0, qData1, qData2) // 批量写入数据信息 if err = Uo.CreatBotUserForexLogList(session, list); err != nil { applogger.Error("%v ForexOpenPosition.CreatBotUserForexLogList:%v", common.ErrForex, err) return flags.ErrMySqlDB } if err = session.Commit(); err != nil { applogger.Error("%v ForexOpenPosition.Commit:%v", common.ErrForex, err) return flags.ErrMySqlDB } return nil } // ForexClosingPosition // // @Description: 外汇平仓处理 // @param ctx // @param db // @param orderId // @param price // @param order // @return error func ForexClosingPosition(ctx context.Context, db *xorm.EngineGroup, orderId string, price string, order structure.ForexOrder) error { session := db.NewSession() defer session.Close() err := session.Begin() if err != nil { applogger.Error("%v ForexClosingPosition.NewSession:%v", common.ErrForex, err) return flags.ErrMySqlDB } // 查询订单信息 tread, err := Uo.GetBotForexTradeByOrderId(session, orderId, flags.PositionStatus) if err != nil { applogger.Error("%v ForexClosingPosition.GetBotForexTradeByOrderId:%v", common.ErrForex, err) return flags.ErrMySqlDB } var userId int64 var dealPrice, earnestMoney, orderNumber, totalAmount, serviceCost decimal.Decimal if tread != nil { userId = int64(tread.UserId) // 用户Id earnestMoney = decimal.RequireFromString(tread.EarnestMoney) // 开仓保证金 orderNumber = decimal.RequireFromString(tread.OrderNumber) // 下单数量 dealPrice = decimal.RequireFromString(tread.DealPrice) // 开仓价格 totalAmount = decimal.RequireFromString(tread.TotalMoney) // 开仓总金额 serviceCost = decimal.RequireFromString(tread.ServiceCost) // 开仓手续费 } if !flags.CheckSetting { applogger.Debug("下单开仓用户Id:%v", userId) applogger.Debug("下单开仓开仓价格:%v", dealPrice) applogger.Debug("下单开仓保证金:%v", earnestMoney) applogger.Debug("下单开仓订单数量:%v", orderNumber) applogger.Debug("下单开仓总金额:%v", totalAmount) applogger.Debug("下单开仓手续费:%v", serviceCost) } // 查询当前下单用户可用账户金额和冻结金额 var usable, frozen, usableNo, frozenNo decimal.Decimal usable, frozen, _, err = Uo.GetBotUserForex(session, userId, flags.ForexUnit) if err != nil { applogger.Error("%v ForexClosingPosition.GetBotUserForex:%v", common.ErrForex, err) return flags.ErrMySqlDB } // 检查用户订单平仓资产 if usable.IsNegative() || frozen.IsNegative() { return flags.ErrContractFive } if !flags.CheckSetting { applogger.Debug("下单可用金额:%v", usable) applogger.Debug("下单冻结金额:%v", frozen) } // 查询当前下单用户可用非账户和冻结金额 if order.ForexId != flags.ForexUnit { usableNo, frozenNo, _, err = Uo.GetBotUserForex(session, userId, order.ForexId) if err != nil { applogger.Error("%vForexClosingPosition.GetBotUserForex:%v", common.ErrForex, err) return flags.ErrMySqlDB } } if !flags.CheckSetting { applogger.Debug("非下单可用金额:%v", usableNo) applogger.Debug("非下单冻结金额:%v", frozenNo) } closeFaceValue := order.System.FaceValue // 面值 // 手续费处理 pryNum := decimal.RequireFromString(order.PryNum) // 杠杆 closePrice := decimal.RequireFromString(price) // 平仓价格 cloePriceCost := closePrice.Mul(orderNumber).String() // 平仓手续费 = 平仓价格 * 仓位数 * 手续费比例 * 面值 cost, err := Uo.CalculateHandlingFees(ctx, session, int(userId), flags.ForexMarketType, flags.ClosingBrokType, orderId, cloePriceCost, closeFaceValue.String()) if err != nil { applogger.Error("%v ForexClosingPosition.CalculateHandlingFees:%v", common.ErrForex, err) return err } closeServiceCost := decimal.RequireFromString(cost) if !flags.CheckSetting { applogger.Debug("平仓价格:%v", closePrice) applogger.Debug("平仓手续费手续费:%v", closeServiceCost) } //已经实现盈亏计算公式(已平仓结算方式) //买涨 已经实现盈亏 = (平仓成交价-开仓成交价)*手数 //买跌 已经实现盈亏 = (开仓成交价-平仓成交价)*手数 var usableNew, frozenNew, usableNewNo, frozenNewNo, subPrice, resultPrice decimal.Decimal switch order.TradeType { case flags.TradeTypeBuy: // 买涨 subPrice = closePrice.Sub(dealPrice) resultPrice = subPrice.Mul(orderNumber).Mul(closeFaceValue).Mul(pryNum) case flags.TradeTypeSell: // 买跌 subPrice = dealPrice.Sub(closePrice) resultPrice = subPrice.Mul(orderNumber).Mul(closeFaceValue).Mul(pryNum) default: } // TODO: 判定亏损不能超过 = 保证金 + 平仓手续费 if resultPrice.IsNegative() { amountLoss := earnestMoney.Sub(closeServiceCost) if resultPrice.Abs().Cmp(amountLoss) >= 0 { resultPrice = amountLoss.Neg() } } // 用户资产账户 usableNew = usable.Add(resultPrice).Add(earnestMoney).Sub(closeServiceCost) // 可用资产 = 原可用资产 + ((正负)盈亏*面值) + 保证金 - 手续费 frozenNew = frozen.Sub(earnestMoney) // 冻结资产 if frozenNew.IsNegative() { frozenNew = decimal.Zero } // 用户非资产账户 if order.ForexId != flags.ForexUnit { usableNewNo = usableNo.Sub(orderNumber) // 可用非资产 = 原可用非资产 - 下单仓位数 frozenNewNo = frozenNo // 可用非冻结资产 } // 检查用户订单平仓资产 if usableNewNo.IsNegative() { return flags.ErrContractFive } if !flags.CheckSetting { applogger.Debug("可用资产:%v", usableNew) applogger.Debug("冻结资产:%v", frozenNew) applogger.Debug("可用非资产:%v", usableNewNo) applogger.Debug("冻结非资产:%v", frozenNewNo) } // 平仓(处理资产表(资产)) userForexUSDT := orders.UpdateBotUserForex(ctx, usableNew.String(), frozenNew.String()) if err = Uo.UpdateBotUserForex(session, userId, flags.ForexUnit, userForexUSDT); err != nil { applogger.Error("%v ForexClosingPosition.UpdateBotUserForex:%v", common.ErrForex, err) return flags.ErrMySqlDB } // 平仓(处理资产表(非资产)) if order.ForexId != flags.ForexUnit { userForex := orders.UpdateBotUserForex(ctx, usableNewNo.String(), frozenNewNo.String()) if err = Uo.UpdateBotUserForex(session, userId, order.ForexId, userForex); err != nil { applogger.Error("%v ForexClosingPosition.UpdateBotUserForex:%v", common.ErrForex, err) return flags.ErrMySqlDB } } // 平仓(处理订单信息(平仓价|保证金|平仓|订单总金额|平仓手续费|完成订单)) trade := orders.UpdateCloseBotForexTrade(ctx, price, earnestMoney.String(), totalAmount.String(), cost) if err = Uo.UpdateBotForexTradeByOrderId(session, orderId, trade); err != nil { applogger.Error("%v ForexClosingPosition.UpdateBotForexTradeByOrderId:%v", common.ErrForex, err) return flags.ErrMySqlDB } // 平仓(返佣记录表|资产表|资金变动表) if err = Uo.ForexRebateCalculation(ctx, session, int(userId), flags.ForexMarketType, flags.ClosingBrokType, flags.CloseMRebate, cost, orderId); err != nil { applogger.Error("%v ForexClosingPosition.ForexRebateCalculation:%v", common.ErrForex, err) return flags.ErrMySqlDB } // 更改交易日志记录方式 var list []models.BotUserForexLog qData0 := orders.CreatBotUserForexLog(ctx, userId, flags.CostMoney, flags.ForexUnit, NegativeValue(closeServiceCost.String()), orderId) // 平仓(资金变动明细表(-平仓手续费)) qData1 := orders.CreatBotUserForexLog(ctx, userId, flags.Thaw, flags.ForexUnit, earnestMoney.String(), orderId) // 平仓(资金变动明细表(+保证金)) qData2 := orders.CreatBotUserForexLog(ctx, userId, flags.TransferOut, order.ForexId, NegativeValue(orderNumber.String()), orderId) // 平仓(资金变动明细表(-非资产)) list = append(list, qData0, qData1, qData2) // 平仓(资金变动明细表(正负盈亏)) if resultPrice.IsNegative() { qData3 := orders.CreatBotUserForexLog(ctx, userId, flags.TransferOut, flags.ForexUnit, resultPrice.String(), orderId) list = append(list, qData3) } else { qData4 := orders.CreatBotUserForexLog(ctx, userId, flags.ChangeInto, flags.ForexUnit, resultPrice.String(), orderId) list = append(list, qData4) } // 平仓(批量写入交易订单日志信息) if err = Uo.CreatBotUserForexLogList(session, list); err != nil { applogger.Error("%v ForexClosingPosition.CreatBotUserForexLogList:%v", common.ErrForex, err) return flags.ErrMySqlDB } if err = session.Commit(); err != nil { applogger.Error("%v ForexClosingPosition.Commit:%v", common.ErrForex, err) return flags.ErrMySqlDB } return nil } // UpdateBotForexStopByOrderId // // @Description: 外汇设置止盈止损 // @receiver uo // @param ctx // @param order // @return bool // @return error func (uo *userOrderRepo) UpdateBotForexStopByOrderId(ctx context.Context, order structure.StopOrder) (bool, error) { session := uo.data.mysqlDB.NewSession() defer session.Close() err := session.Begin() if err != nil { applogger.Error("%v UpdateBotForexStopByOrderId.NewSession:%v", common.ErrForex, err) return false, flags.ErrMySqlDB } // 设置止盈止损判定 trade, err := uo.GetBotForexTradeByOrderId(session, order.OrderId, flags.PositionStatus) if err != nil || trade == nil { applogger.Error("%v UpdateBotForexStopByOrderId.GetBotForexTradeByOrderId:%v", common.ErrForex, err) return false, flags.ErrMySqlDB } // 下单信息 checkBool, stopWinPrice, stopLossPrice, err := uo.UpdateForexVoteStopType(order) if err != nil { applogger.Error("%v UpdateBotForexStopByOrderId.UpdateForexVoteStopType:%v", common.ErrForex, err) return false, err } if !flags.CheckSetting { applogger.Debug("获取当前止盈止损数据:%v,%v,%v", checkBool, stopWinPrice, stopLossPrice) } // 下单判定设置(限价|市价|开仓价) limitOrMarketPrice, err := uo.UpdateForexVoteDealType(trade) if err != nil { applogger.Error("%v UpdateBotForexStopByOrderId.UpdateForexVoteDealType:%v", common.ErrForex, err) return false, err } if !flags.CheckSetting { applogger.Debug("获取当前开仓价格:%v", limitOrMarketPrice) } // 下单判定设置(买涨|买跌) if err = uo.ForexVoteTradeType(int64(trade.TradeType), stopWinPrice, stopLossPrice, limitOrMarketPrice, checkBool); err != nil { applogger.Error("%v UpdateBotForexStopByOrderId.ForexVoteTradeType:%v", common.ErrForex, err) return false, err } // 更新订单表 botStockTrade := orders.BotForexStopByOrderId(ctx, order) err = uo.UpdateBotForexTradeByOrderId(session, order.OrderId, botStockTrade) if err != nil { applogger.Error("%v UpdateBotForexStopByOrderId.Update:%v", common.ErrForex, err) return false, flags.ErrMySqlDB } // 修改挂单缓存队列 entrust, err := LoadLRangeList(setting.MarketForexPosition) if err != nil { applogger.Error("%v UpdateBotForexStopByOrderId.LoadLRangeList:%v", common.ErrForex, err) return false, flags.ErrCacheDB } for key, value := range entrust { var entrustJson forexd.ForexTallyCache if err = json.Unmarshal([]byte(value), &entrustJson); err != nil { applogger.Error("%v UpdateBotForexStopByOrderId.Unmarshal:%v", common.ErrForex, err) return false, flags.ErrCacheDB } entrustJson.Order.StopType = order.StopType entrustJson.Order.StopWinPrice = order.StopWinPrice entrustJson.Order.StopLossPrice = order.StopLossPrice if !flags.CheckSetting { applogger.Debug("修改缓存中的止盈止损Type:%v", entrustJson.Order.StopType) applogger.Debug("修改缓存中的止盈:%v", entrustJson.Order.StopWinPrice) applogger.Debug("修改缓存中的止损:%v", entrustJson.Order.StopLossPrice) } var data []byte data, err = json.Marshal(&entrustJson) if err != nil { applogger.Error("%v UpdateBotForexStopByOrderId.Marshal:%v", common.ErrForex, err) return false, flags.ErrCacheDB } if order.OrderId == entrustJson.OrderId { if err = Reds.HSet(context.Background(), setting.MarketForexPosition, key, string(data)).Err(); err != nil { applogger.Error("%v UpdateBotForexStopByOrderId.HSet:%v", common.ErrForex, err) return false, flags.ErrCacheDB } } } if err = session.Commit(); err != nil { applogger.Error("%v UpdateBotForexStopByOrderId.Commit:%v", common.ErrForex, err) return false, flags.ErrMySqlDB } return true, nil } // UpdateBotForexCancelByOrderId // // @Description: 外汇撤单 // @receiver uo // @param ctx // @param orderId // @return bool // @return error func (uo *userOrderRepo) UpdateBotForexCancelByOrderId(ctx context.Context, orderId string) (bool, error) { session := uo.data.mysqlDB.NewSession() defer session.Close() err := session.Begin() if err != nil { applogger.Error("%v UpdateBotForexCancelByOrderId.NewSession:%v", common.ErrForex, err) return false, flags.ErrMySqlDB } // get BotForexTrade tread, err := uo.GetBotForexTradeByOrderId(session, orderId, flags.EntrustStatus) if err != nil { applogger.Error("%v UpdateBotForexCancelByOrderId.GetBotForexTradeByOrderId:%v", common.ErrForex, err) return false, flags.ErrMySqlDB } var userId int64 var earnestMoneyT, serviceCostT, symbol, orderNumber string if tread != nil { userId = int64(tread.UserId) earnestMoneyT = tread.EarnestMoney serviceCostT = tread.ServiceCost orderNumber = tread.OrderNumber symbol = tread.ContractId } // get BotUserStock By USD var usable, frozen, usableNo, frozenNo decimal.Decimal usable, frozen, _, err = uo.GetBotUserForex(session, userId, flags.ForexUnit) if err != nil { applogger.Error("%v UpdateBotForexCancelByOrderId.GetBotUserForex:%v", common.ErrForex, err) return false, flags.ErrMySqlDB } // 检查用户订单撤单资产 if frozen.IsNegative() || usable.IsNegative() { return false, flags.ErrPublicFour } if !flags.CheckSetting { applogger.Debug("用户原始可用资金:%v", usable) applogger.Debug("用户原始冻结资金:%v", frozen) } if symbol != flags.ForexUnit { usableNo, frozenNo, _, err = uo.GetBotUserForex(session, userId, tread.ContractId) if err != nil { applogger.Error("%v UpdateBotForexCancelByOrderId.GetBotUserForex:%v", common.ErrForex, err) return false, flags.ErrPublicFour } } if !flags.CheckSetting { applogger.Debug("用户原始可用非资金:%v", usableNo) applogger.Debug("用户原始冻结非资金:%v", frozenNo) } // 更新订单信息 botStockTrade := orders.BotForexCancelByOrderId(ctx) if err = uo.UpdateBotForexTradeByOrderId(session, orderId, botStockTrade); err != nil { applogger.Error("%v UpdateBotForexCancelByOrderId.UpdateBotForexTradeByOrderId:%v", common.ErrForex, err) return false, flags.ErrPublicFour } // Operational Spot Asset Table earnestMoney := decimal.RequireFromString(earnestMoneyT) // 保证金 serviceCost := decimal.RequireFromString(serviceCostT) // 订单手续费 totalMoney := earnestMoney.Add(serviceCost) // 订单总金额 if !flags.CheckSetting { applogger.Debug("撤单用户ID:%v", userId) applogger.Debug("下单交易对:%v", symbol) applogger.Debug("撤单订单保证金:%v", earnestMoneyT) applogger.Debug("撤单手续费:%v", serviceCostT) applogger.Debug("撤单订单数量:%v", orderNumber) applogger.Debug("撤单总金额数量:%v", totalMoney) } // Update total asset data usableNew := usable.Add(totalMoney) // 用户总资产 frozenNew := frozen.Sub(totalMoney) // 用户冻结资产 usableNoNew := usableNo // 用户非可用资产 frozenNoNew := frozenNo // 用户非冻结资产 // 检查用户订单撤单资产 if frozenNew.IsNegative() { return false, flags.ErrContractSeven } if !flags.CheckSetting { applogger.Debug("用户撤单可用总资产:%v", usableNew) applogger.Debug("用户撤单冻结总资产:%v", frozenNew) applogger.Debug("用户非撤单可用总资产:%v", usableNoNew) applogger.Debug("用户非撤单冻结总资产:%v", frozenNoNew) } userForexUSDT := orders.UpdateBotUserForex(ctx, usableNew.String(), frozenNew.String()) if err = uo.UpdateBotUserForex(session, userId, flags.ForexUnit, userForexUSDT); err != nil { applogger.Error("%v UpdateBotForexCancelByOrderId.UpdateBotUserForex:%v", common.ErrForex, err) return false, flags.ErrMySqlDB } if symbol != flags.ForexUnit { userForex := orders.UpdateBotUserForex(ctx, usableNoNew.String(), frozenNoNew.String()) if err = uo.UpdateBotUserForex(session, userId, tread.ContractId, userForex); err != nil { applogger.Error("%v UpdateBotForexCancelByOrderId.UpdateBotUserForex:%v", common.ErrForex, err) return false, flags.ErrMySqlDB } } // 清理挂单缓存信息 if err = Reds.HDel(context.Background(), setting.MarketForexEntrust, orderId).Err(); err != nil { applogger.Error("%v UpdateBotForexCancelByOrderId.HDel:%v", common.ErrForex, err) return false, flags.ErrCacheDB } // 撤单更新订阅缓存订单状态 userSubKey := virtual.OrderIdListKey(setting.ForexSubscribe, userId) if err = UpdateForexSubscribeHashStatusByOrderId(orderId, userSubKey, flags.Cancel, flags.SetNull); err != nil { applogger.Error("%v UpdateBotForexCancelByOrderId.ForexSubscribe:%v", common.ErrForex, err) return false, flags.ErrCacheDB } // 撤单更新管理员订阅缓存订单状态 if err = UpdateForexSubscribeHashStatusByOrderId(orderId, setting.AdminForexSubscribe, flags.Cancel, flags.SetNull); err != nil { applogger.Error("%v UpdateBotForexCancelByOrderId.AdminForexSubscribe:%v", common.ErrForex, err) return false, flags.ErrCacheDB } if err = session.Commit(); err != nil { applogger.Error("%v UpdateBotForexCancelByOrderId.Commit:%v", common.ErrForex, err) return false, flags.ErrMySqlDB } return true, nil } // UpdateBotForexClosingByOrderId // // @Description: 外汇平仓 // @receiver uo // @param ctx // @param orderId // @return bool // @return error func (uo *userOrderRepo) UpdateBotForexClosingByOrderId(ctx context.Context, orderId string) (bool, error) { // 1、订单信息 entrust, err := Reds.HGet(context.Background(), setting.MarketForexPosition, orderId).Result() if err != nil { applogger.Error("%v UpdateBotForexClosingByOrderId.MarketForexPosition.HGet:%v", common.ErrForex, err) return false, flags.ErrMySqlDB } var entrustJson forexd.ForexTallyCache if err = json.Unmarshal([]byte(entrust), &entrustJson); err != nil { applogger.Error("%v UpdateBotForexClosingByOrderId.Unmarshal:%v", common.ErrForex, err) return false, flags.ErrCacheDB } if !flags.CheckSetting { applogger.Debug("手动平仓:%v", entrustJson) } // 2、当前最新价格 var openPrice string //switch entrustJson.Order.TradeType { //case 1: // 外汇交易对买一最新报价 // subKey := publicData.SymbolCache(flags.Wh, entrustJson.Symbol, flags.TradeTypeBuy) // openPrice, err = forexd.ForexSubMarketPrice(ctx, subKey) // 外汇交易对买一最新报价 // if err != nil { // return false, flags.ErrContractEight // } //case 2: // 外汇交易对卖一最新报价 // subKey := publicData.SymbolCache(flags.Wh, entrustJson.Symbol, flags.TradeTypeSell) // openPrice, err = forexd.ForexSubMarketPrice(ctx, subKey) // 外汇交易对卖一最新报价 // if err != nil { // return false, flags.ErrContractEight // } //default: // return false, flags.ErrContractEight //} newPrice, err := GetForexPriceNew(entrustJson.Symbol, entrustJson.Order.TradeType) if err != nil { applogger.Warn("%v UpdateBotForexClosingByOrderId.GetForexPriceNew:%v", common.ErrForex, err) return false, err } openPrice = newPrice.String() if err = Reds.HDel(context.Background(), setting.MarketForexPosition, orderId).Err(); err != nil { applogger.Error("%v UpdateBotForexClosingByOrderId.MarketForexPosition.HDel:%v", common.ErrForex, err) return false, flags.ErrCacheDB } // 3、平仓处理 if err = ForexClosingPosition(ctx, uo.data.mysqlDB, orderId, openPrice, entrustJson.Order); err != nil { applogger.Error("%v UpdateBotForexClosingByOrderId.ForexClosingPosition:%v", common.ErrForex, err) return false, flags.ErrCacheDB } // 4、平仓更新订阅缓存订单状态 userSubKey := virtual.OrderIdListKey(setting.ForexSubscribe, entrustJson.UserId) if err = UpdateForexSubscribeHashStatusByOrderId(orderId, userSubKey, flags.Close, flags.SetNull); err != nil { applogger.Error("%v UpdateBotForexClosingByOrderId.ForexSubscribe:%v", common.ErrForex, err) return false, flags.ErrCacheDB } // 5、平仓更新管理员订阅缓存订单状态 if err = UpdateForexSubscribeHashStatusByOrderId(orderId, setting.AdminForexSubscribe, flags.Close, flags.SetNull); err != nil { applogger.Error("%v UpdateBotForexCancelByOrderId.AdminForexSubscribe:%v", common.ErrForex, err) return false, flags.ErrCacheDB } return true, nil } // UpdateBotForexClosingAllByOrderId // // @Description: 外汇一键平仓 // @receiver uo // @param ctx // @param userId // @return error func (uo *userOrderRepo) UpdateBotForexClosingAllByOrderId(ctx context.Context, userId int64) error { // 1、查询当前用户所有订单 orderMap, err := uo.GetBotForexTradeByUserId(userId) if err != nil { applogger.Error("%v UpdateBotForexClosingAllByOrderId.GetBotForexTradeByUserId:%v", common.ErrForex, err) return flags.ErrMySqlDB } // 2、查询持仓缓存列表数据-1>清理持仓列表缓存 2>处理平仓数据 3>清理订单ID缓存列表 for _, value := range orderMap { var entrust string entrust, err = Reds.HGet(context.Background(), setting.MarketForexPosition, value).Result() if err != nil { applogger.Error("%v UpdateBotForexClosingAllByOrderId.MarketForexPosition.LRange:%v", common.ErrForex, err) return flags.ErrCacheDB } var entrustJson forexd.ForexTallyCache if err = json.Unmarshal([]byte(entrust), &entrustJson); err != nil { applogger.Error("%v UpdateBotForexClosingAllByOrderId.Unmarshal:%v", common.ErrForex, err) return flags.ErrCacheDB } // 获取当前外汇交易对买一卖一最新报价 var openPrice string //switch entrustJson.Order.TradeType { //case 1: // 外汇交易对买一最新报价 // subKey := publicData.SymbolCache(flags.Wh, entrustJson.Symbol, flags.TradeTypeBuy) // openPrice, err = forexd.ForexSubMarketPrice(ctx, subKey) // 外汇交易对买一最新报价 // if err != nil { // return flags.ErrContractEight // } //case 2: // 外汇交易对卖一最新报价 // subKey := publicData.SymbolCache(flags.Wh, entrustJson.Symbol, flags.TradeTypeSell) // openPrice, err = forexd.ForexSubMarketPrice(ctx, subKey) // 外汇交易对卖一最新报价 // if err != nil { // return flags.ErrContractEight // } //default: // return flags.ErrContractEight //} newPrice, err := GetForexPriceNew(entrustJson.Symbol, entrustJson.Order.TradeType) if err != nil { applogger.Warn("%v UpdateBotForexClosingAllByOrderId.GetForexPriceNew:%v", common.ErrForex, err) return flags.ErrCacheDB } openPrice = newPrice.String() // 清理持仓缓存列表 if err = Reds.HDel(context.Background(), setting.MarketForexPosition, value).Err(); err != nil { applogger.Error("%v UpdateBotForexClosingAllByOrderId.MarketForexPosition.HDel:%v", common.ErrForex, err) return flags.ErrCacheDB } // 平仓 if err = ForexClosingPosition(ctx, uo.data.mysqlDB, entrustJson.OrderId, openPrice, entrustJson.Order); err != nil { applogger.Error("%v UpdateBotForexClosingAllByOrderId.ForexClosingPosition:%v", common.ErrForex, err) return err } // 平仓更新用户订阅订单状态 userSubKey := virtual.OrderIdListKey(setting.ForexSubscribe, entrustJson.UserId) if err = UpdateForexSubscribeHashStatusByOrderId(entrustJson.OrderId, userSubKey, flags.Close, flags.SetNull); err != nil { applogger.Error("%v UpdateBotForexClosingAllByOrderId.ForexSubscribe:%v", common.ErrForex, err) return flags.ErrMySqlDB } // 平仓更新管理员订阅订单状态 if err = UpdateForexSubscribeHashStatusByOrderId(entrustJson.OrderId, setting.AdminForexSubscribe, flags.Close, flags.SetNull); err != nil { applogger.Error("%v UpdateBotForexCancelByOrderId.AdminForexSubscribe:%v", common.ErrForex, err) return flags.ErrMySqlDB } } return nil } // GetBotForexTradeByOrderId // // @Description: // @receiver uo // @param ctx // @param session // @param orderId // @param status // @return *models.BotForexTrade // @return error func (uo *userOrderRepo) GetBotForexTradeByOrderId(session *xorm.Session, orderId string, status int) (*models.BotForexTrade, error) { var botForexTrade []models.BotForexTrade if err := session.Table(flags.BotForexTrade). Where("order_id = ?", orderId). Where("`status` = ?", status). Find(&botForexTrade); err != nil { return nil, err } for _, value := range botForexTrade { return &value, nil } return nil, nil } // GetBotForexTradeByUserId // // @Description: // @receiver uo // @param ctx // @param userId // @return map[string]string // @return error func (uo *userOrderRepo) GetBotForexTradeByUserId(userId int64) (map[string]string, error) { var botForexTrade []models.BotForexTrade if err := uo.data.mysqlDB.Table(flags.BotForexTrade). Where("user_id = ? ", userId). Where("status = 1"). Find(&botForexTrade); err != nil { return nil, err } botMap := make(map[string]string) for _, value := range botForexTrade { botMap[value.OrderId] = value.OrderId } return botMap, nil } // GetBotUserForex // // @Description: // @receiver uo // @param ctx // @param session // @param userId // @param symbol // @return decimal.Decimal // @return decimal.Decimal // @return int // @return error func (uo *userOrderRepo) GetBotUserForex(session *xorm.Session, userId int64, symbol string) (decimal.Decimal, decimal.Decimal, int, error) { var contractUSDT []models.BotUserForex if err := session.Table(flags.BotUserForex). Where("user_id = ?", userId). Where("contract_id = ?", strings.ToUpper(symbol)). Find(&contractUSDT); err != nil { return decimal.Zero, decimal.Zero, 0, err } var usableNum, frozenNum decimal.Decimal for _, value := range contractUSDT { usableNum = decimal.RequireFromString(value.UsableNum) // 资产可用余额 frozenNum = decimal.RequireFromString(value.FrozenNum) // 资产冻结数量 } return usableNum, frozenNum, len(contractUSDT), nil } // ForexVoteDealType // // @Description: // @receiver uo // @param ctx // @param order // @return decimal.Decimal // @return error func (uo *userOrderRepo) ForexVoteDealType(order structure.ForexOrder) (decimal.Decimal, error) { var limitOrMarketPrice decimal.Decimal switch order.DealType { case flags.DealTypeLimited: // 限价 if len(order.LimitPrice) != 0 { limitOrMarketPrice = decimal.RequireFromString(order.LimitPrice) } case flags.DealTypeMarket: // 市价 if len(order.MarketPrice) != 0 { limitOrMarketPrice = decimal.RequireFromString(order.MarketPrice) } default: return decimal.Decimal{}, flags.ErrPublicFive } return limitOrMarketPrice, nil } // UpdateForexVoteDealType // // @Description: // @receiver uo // @param ctx // @param order // @return decimal.Decimal // @return error func (uo *userOrderRepo) UpdateForexVoteDealType(order *models.BotForexTrade) (decimal.Decimal, error) { var limitOrMarketPrice decimal.Decimal switch order.DealType { case flags.DealTypeLimited: // 限价 if len(order.LimitPrice) != 0 { limitOrMarketPrice = decimal.RequireFromString(order.LimitPrice) } case flags.DealTypeMarket: // 市价 if len(order.MarketPrice) != 0 { limitOrMarketPrice = decimal.RequireFromString(order.MarketPrice) } default: return decimal.Decimal{}, flags.ErrPublicFive } if len(order.DealPrice) != 0 { dealPrice := decimal.RequireFromString(order.DealPrice) if !dealPrice.IsZero() { limitOrMarketPrice = dealPrice } } return limitOrMarketPrice, nil } // UpdateForexVoteStopType // // @Description: // @receiver uo // @param ctx // @param order // @return bool // @return decimal.Decimal // @return decimal.Decimal // @return error func (uo *userOrderRepo) UpdateForexVoteStopType(order structure.StopOrder) (bool, decimal.Decimal, decimal.Decimal, error) { var checkBool bool var stopWinPrice, stopLossPrice decimal.Decimal switch order.StopType { case flags.StopTypeNone: // 暂无设置止盈止损 checkBool = false case flags.StopTypeSet: // 设置止盈止损 if len(order.StopWinPrice) != 0 { stopWinPrice = decimal.RequireFromString(order.StopWinPrice) } if len(order.StopLossPrice) != 0 { stopLossPrice = decimal.RequireFromString(order.StopLossPrice) } // 判定设置是否都为零 if stopWinPrice.IsZero() && stopLossPrice.IsZero() { return checkBool, decimal.Decimal{}, decimal.Decimal{}, flags.ErrContractTen } else { checkBool = true } default: return checkBool, stopWinPrice, stopLossPrice, flags.ErrContractEleven } return checkBool, stopWinPrice, stopLossPrice, nil } // ForexVoteTradeType // // @Description: 股票判定止盈止损配置 // @receiver uo // @param ctx // @param tradeType // @param stopWinPrice // @param stopLossPrice // @param price // @param checkBool // @return error func (uo *userOrderRepo) ForexVoteTradeType(tradeType int64, stopWinPrice, stopLossPrice, price decimal.Decimal, checkBool bool) error { if checkBool { switch tradeType { case flags.TradeTypeBuy: // 买涨 if !stopWinPrice.IsZero() { if stopWinPrice.Cmp(price) <= 0 { // 限价买涨下单,止盈价格必须大于限价 return flags.ErrBuyStopWinPrice } } if !stopLossPrice.IsZero() { if stopLossPrice.Cmp(price) >= 0 { // 限价买涨下单,止损价格必须小于限价 return flags.ErrBuyStopLossPrice } } case flags.TradeTypeSell: // 买跌 if !stopWinPrice.IsZero() { if stopWinPrice.Cmp(price) >= 0 { // 限价买跌下单,止盈价格必须小于限价 return flags.ErrSellStopWinPrice } } if !stopLossPrice.IsZero() { if stopLossPrice.Cmp(price) <= 0 { // 限价买跌下单,止损价格必须大于限价 return flags.ErrSellStopLossPrice } } default: return flags.ErrContractTwelve } } return nil } // CreatBotUserForex // // @Description: // @receiver uo // @param ctx // @param session // @param digital // @return error func (uo *userOrderRepo) CreatBotUserForex(session *xorm.Session, digital models.BotUserForex) error { _, err := session.Table(flags.BotUserForex).Insert(&digital) if err != nil { return err } return nil } // CreatBotForexTrade // // @Description: // @receiver uo // @param ctx // @param session // @param trade // @return error func (uo *userOrderRepo) CreatBotForexTrade(session *xorm.Session, trade models.BotForexTrade) error { _, err := session.Table(flags.BotForexTrade).Insert(&trade) if err != nil { return err } return nil } // UpdateBotForexTradeByOrderId // // @Description: // @receiver uo // @param ctx // @param session // @param orderId // @param trade // @return error func (uo *userOrderRepo) UpdateBotForexTradeByOrderId(session *xorm.Session, orderId string, trade models.BotForexTrade) error { _, err := session.Table(flags.BotForexTrade). Where("order_id = ?", orderId). Update(&trade) if err != nil { return err } return nil } // UpdateBotUserForex // // @Description: // @receiver uo // @param ctx // @param session // @param userId // @param symbol // @param userForex // @return error func (uo *userOrderRepo) UpdateBotUserForex(session *xorm.Session, userId int64, symbol string, userForex models.BotUserForex) error { _, err := session.Table(flags.BotUserForex). Where("user_id = ?", userId). Where("contract_id = ?", symbol). Update(&userForex) if err != nil { return err } return nil } // VerifyBotForexTradeOrderId // // @Description: // @receiver uo // @param ctx // @param session // @return string // @return error func (uo *userOrderRepo) VerifyBotForexTradeOrderId(session *xorm.Session) (string, error) { var orderId string for { orderId = orders.CreateRandCodeOrder(10) var orderList []models.BotForexTrade err := session.Table(flags.BotForexTrade).Where("order_id = ?", orderId).Find(&orderList) if err != nil || len(orderList) > 0 { applogger.Error("%v VerifyBotForexTradeOrderId.Find:%v", common.ErrForex, err) continue } break } return orderId, nil }