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.
1499 lines
58 KiB
1499 lines
58 KiB
2 months ago
|
package data
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"encoding/json"
|
||
|
"github.com/go-xorm/xorm"
|
||
|
"github.com/shopspring/decimal"
|
||
|
"matchmaking-system/internal/biz/structure"
|
||
|
"matchmaking-system/internal/data/socket/publicData"
|
||
|
"matchmaking-system/internal/data/tradedeal/share"
|
||
|
"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"
|
||
|
"time"
|
||
|
|
||
|
orders "matchmaking-system/internal/data/convert"
|
||
|
models "matchmaking-system/internal/pkg/model"
|
||
|
)
|
||
|
|
||
|
// GetBotStockIdnTradeList
|
||
|
//
|
||
|
// @Description: 印尼股订单列表查询
|
||
|
// @receiver uo
|
||
|
// @param ctx
|
||
|
// @param pageSize
|
||
|
// @param pageCount
|
||
|
// @param userId
|
||
|
// @param status
|
||
|
// @return []*models.BotStockIdnTrade
|
||
|
// @return int64
|
||
|
// @return error
|
||
|
func (uo *userOrderRepo) GetBotStockIdnTradeList(pageSize, pageCount, userId, status int64) ([]*models.BotStockIdnTrade, int64, error) {
|
||
|
totalCount, err := uo.data.mysqlDB.Table(flags.BotStockIdnTrade).
|
||
|
Where("user_id = ?", userId).
|
||
|
Where("status = ?", status).
|
||
|
Count()
|
||
|
if err != nil {
|
||
|
return nil, 0, flags.ErrMySqlDB
|
||
|
}
|
||
|
if totalCount == 0 {
|
||
|
return nil, 0, nil
|
||
|
}
|
||
|
var stockList []*models.BotStockIdnTrade
|
||
|
if err = uo.data.mysqlDB.Table(flags.BotStockIdnTrade).
|
||
|
Where("user_id = ?", userId).
|
||
|
Where("status = ?", status).
|
||
|
Limit(int(pageSize), int(pageCount)).
|
||
|
Desc(GetOrderByStatusSort(status)).
|
||
|
Find(&stockList); err != nil {
|
||
|
return nil, 0, flags.ErrMySqlDB
|
||
|
}
|
||
|
|
||
|
var stockUpdateList []*models.BotStockIdnTrade
|
||
|
for _, value := range stockList {
|
||
|
value.KeepDecimal = GetKeepDecimal(flags.StockYNSystemSetUpKey, value.StockId)
|
||
|
value.StockName = GetStockName(flags.StockYNSystemSetUpKey, value.StockId)
|
||
|
stockUpdateList = append(stockUpdateList, value)
|
||
|
}
|
||
|
|
||
|
return stockUpdateList, totalCount, nil
|
||
|
}
|
||
|
|
||
|
// PlacingStockIdnOrders
|
||
|
//
|
||
|
// @Description: 印尼股下单
|
||
|
// @receiver uo
|
||
|
// @param ctx
|
||
|
// @param userId
|
||
|
// @param order
|
||
|
// @return string
|
||
|
// @return error
|
||
|
func (uo *userOrderRepo) PlacingStockIdnOrders(ctx context.Context, userId int64, order structure.ShareOrder) (string, error) {
|
||
|
// 1、通知股下单订阅
|
||
|
symbol := order.StockId
|
||
|
timeValue := QuerySystemCache(flags.ShareIdnMarketType) // 市场开闭盘时间
|
||
|
if !utils.CheckInPlateTime(timeValue) {
|
||
|
return flags.SetNull, flags.ErrStopTread
|
||
|
}
|
||
|
SubscribeIdnHSetCodeList(symbol, false) // 同步写入股票列表缓存
|
||
|
SubscribeIdnCloseNewPrice(symbol) // 同步股票实时行情价
|
||
|
|
||
|
// 判定是否存在欠款订单
|
||
|
userIdMap, _ := GetBotUserArrears(ctx)
|
||
|
_, isOk := userIdMap[userId]
|
||
|
if isOk {
|
||
|
return flags.ErrPublicServe.Error(), nil
|
||
|
}
|
||
|
|
||
|
order = PryNumInit(order) // 杠杆初始化
|
||
|
subKey := publicData.SymbolCache(flags.Idn, symbol, flags.TradeTypePrice)
|
||
|
|
||
|
// 印尼股市场系统设置
|
||
|
if CheckGlobalTread(flags.IdnMarket) {
|
||
|
return flags.SetNull, flags.ErrStopTread
|
||
|
}
|
||
|
|
||
|
// 全局设置交易操作
|
||
|
var blockTime time.Time
|
||
|
var priceNew, userKey, adminKey string
|
||
|
if !CheckTypeStatus(order.Type) {
|
||
|
userKey = setting.ShareIdnSubscribe
|
||
|
adminKey = setting.AdminShareIdnSubscribe
|
||
|
} else {
|
||
|
// 判定:1、是否开启股票交易 2、是否在交易时间内 3、是否达到最小交易量
|
||
|
check, openPrice, minNum, endTime := CheckBlockTread(flags.IdnBlk, symbol)
|
||
|
if check {
|
||
|
return flags.SetNull, flags.ErrShareSeven
|
||
|
}
|
||
|
if minNum > utils.StringToInt(order.OrderNumber) {
|
||
|
return flags.SetNull, flags.ErrShareSix
|
||
|
}
|
||
|
priceNew = openPrice // 开仓价格
|
||
|
blockTime = endTime // 平仓时间
|
||
|
userKey = setting.ShareBlkSubscribe
|
||
|
adminKey = setting.AdminShareBlkSubscribe
|
||
|
}
|
||
|
flatRatio := GetCacheForcedClosure(flags.StockYNSystemSetUpKey, symbol) // 单个股票系统设置
|
||
|
leverStatus := SystemShareMarketLeverStatus(flags.StockMarketList, flags.IdnMarket, userId) // 股票市场系统设置
|
||
|
system := &structure.ShareSystem{
|
||
|
StrongFlatRatio: flatRatio.String(), // 强平阈值
|
||
|
Status: leverStatus.Status, // 杠杆状态
|
||
|
StockMin: leverStatus.StockMin, // 开启杠杆的最小值
|
||
|
LevelMin: leverStatus.LevelMin, // 杠杆最小值
|
||
|
LevelMax: leverStatus.LevelMax, // 杠杆最大值
|
||
|
UserStatus: leverStatus.UserStatus, // 用户开启状态
|
||
|
}
|
||
|
order.System = system
|
||
|
|
||
|
// 2、股票下单判定
|
||
|
// 下单判定设置(false无设置|true止盈止损)
|
||
|
checkBool, stopWinPrice, stopLossPrice, err := StockIdnVoteStopType(order)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v PlacingStockIdnOrders.StockIdnVoteStopType:%v", common.ErrShareIdn, err)
|
||
|
return flags.SetNull, err
|
||
|
}
|
||
|
// 下单判定设置(限价|市价)
|
||
|
limitOrMarketPrice, err := uo.StockIdnVoteDealType(order)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v PlacingStockIdnOrders.StockVoteDealType:%v", common.ErrShareIdn, err)
|
||
|
return flags.SetNull, err
|
||
|
}
|
||
|
// 下单判定设置(买涨|买跌)
|
||
|
if err = uo.VoteTradeType(order.TradeType, stopWinPrice, stopLossPrice, limitOrMarketPrice, checkBool); err != nil {
|
||
|
applogger.Error("%v PlacingStockIdnOrders.StockVoteTradeType:%v", common.ErrShareIdn, err)
|
||
|
return flags.SetNull, err
|
||
|
}
|
||
|
|
||
|
// 3、订单持久化录入(并处理资产信息)
|
||
|
pryNum := SystemDealWithLever(order)
|
||
|
orderId, err := uo.StockIdnOrderWriteDB(ctx, userId, order, limitOrMarketPrice, pryNum)
|
||
|
if err != nil || len(orderId) == 0 {
|
||
|
applogger.Error("%v PlacingStockIdnOrders.StockIdnOrderWriteDB:%v", common.ErrShareIdn, err)
|
||
|
return flags.SetNull, err
|
||
|
}
|
||
|
|
||
|
// 4、处理订单信息
|
||
|
chg := GetShareChgIdn(flags.Idn, order.StockId) // 涨跌幅标识值
|
||
|
closingTime := SystemTimeGenerate(flags.StockMarketList, flags.IdnMarket, time.Now()) // 开盘时间
|
||
|
marketStatus, shareOrder, err := share.ShareIdnCacheDeal(ctx, userId, orderId, subKey, order, chg, priceNew, closingTime, blockTime)
|
||
|
if err != nil || shareOrder == nil {
|
||
|
applogger.Error("%v PlacingStockIdnOrders.ShareIdnCacheDeal:%v", common.ErrShareIdn, err)
|
||
|
return flags.SetNull, err
|
||
|
}
|
||
|
// 计算保证金 = 订单价格 * 订单数量 / 杠杆
|
||
|
shareOrder.Order.MarketMoney = limitOrMarketPrice.Mul(decimal.RequireFromString(order.OrderNumber)).Div(pryNum).String()
|
||
|
if !flags.CheckSetting {
|
||
|
applogger.Debug("订单ID:%v", shareOrder.OrderId)
|
||
|
applogger.Debug("订单交易对:%v", shareOrder.Symbol)
|
||
|
applogger.Debug("订单状态:%v", shareOrder.Status)
|
||
|
applogger.Debug("订单用户ID:%v", shareOrder.UserId)
|
||
|
applogger.Debug("开盘价:%v", shareOrder.OpenPrice)
|
||
|
applogger.Debug("收盘价:%v", shareOrder.ClosingPrice)
|
||
|
applogger.Debug("下单信息:%v", shareOrder.Order)
|
||
|
}
|
||
|
|
||
|
// 6、订单(挂单|持仓)缓存列表,等待队列计算
|
||
|
if err = share.ShareIdnHashUserOrder(Reds, marketStatus, shareOrder); err != nil {
|
||
|
applogger.Error("%v PlacingStockIdnOrders.ShareIdnHashUserOrder:%v", common.ErrShareIdn, err)
|
||
|
return flags.SetNull, flags.ErrCacheDB
|
||
|
}
|
||
|
|
||
|
// 7、用户订阅股票订单信息
|
||
|
orderIdKey := virtual.OrderIdListKey(userKey, userId)
|
||
|
if err = share.ShareIdnHashUserOrder(Reds, orderIdKey, shareOrder); err != nil {
|
||
|
applogger.Error("%v PlacingStockIdnOrders.%v:%v", common.ErrShareIdn, userKey, err)
|
||
|
return flags.SetNull, flags.ErrCacheDB
|
||
|
}
|
||
|
|
||
|
// 8、管理员订阅订单信息
|
||
|
if err = share.ShareIdnHashUserOrder(Reds, adminKey, shareOrder); err != nil {
|
||
|
applogger.Error("%v PlacingStockIdnOrders.%v:%v", common.ErrShareIdn, adminKey, err)
|
||
|
return flags.SetNull, flags.ErrCacheDB
|
||
|
}
|
||
|
|
||
|
return orderId, nil
|
||
|
}
|
||
|
|
||
|
// StockIdnOrderWriteDB
|
||
|
//
|
||
|
// @Description: 印尼股下单处理
|
||
|
// @receiver uo
|
||
|
// @param ctx
|
||
|
// @param userId
|
||
|
// @param order
|
||
|
// @return string
|
||
|
// @return error
|
||
|
func (uo *userOrderRepo) StockIdnOrderWriteDB(ctx context.Context, userId int64, order structure.ShareOrder, limitOrMarketPrice, lever decimal.Decimal) (string, error) {
|
||
|
session := uo.data.mysqlDB.NewSession()
|
||
|
defer session.Close()
|
||
|
err := session.Begin()
|
||
|
if err != nil {
|
||
|
applogger.Error("%v StockIdnOrderWriteDB.Begin:%v", common.ErrShareIdn, err)
|
||
|
return flags.SetNull, flags.ErrMySqlDB
|
||
|
}
|
||
|
|
||
|
// 当前下单用户的资产
|
||
|
var usableOld, frozenOld decimal.Decimal
|
||
|
stockIdr, err := uo.GetBotUserStockIdnByUserIdAndStockId(session, userId, flags.ShareIdnBasicUnit)
|
||
|
if err != nil || stockIdr == nil {
|
||
|
applogger.Error("%v StockIdnOrderWriteDB.IDR:%v", common.ErrShareIdn, err)
|
||
|
return flags.SetNull, flags.ErrMySqlDB
|
||
|
}
|
||
|
usableOld = decimal.RequireFromString(stockIdr.UsableNum)
|
||
|
frozenOld = decimal.RequireFromString(stockIdr.FrozenNum)
|
||
|
|
||
|
// 检查用户下单资产
|
||
|
if usableOld.IsZero() || usableOld.IsNegative() || frozenOld.IsNegative() {
|
||
|
return flags.SetNull, flags.ErrShareOne
|
||
|
}
|
||
|
|
||
|
// 当前系统下单用户的非资产
|
||
|
var usableFOld, frozenFOld decimal.Decimal
|
||
|
stockFIdr, err := uo.GetBotUserStockIdnByUserIdAndStockId(session, userId, order.StockId)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v StockIdnOrderWriteDB.FeiIDR:%v", common.ErrShareIdn, err)
|
||
|
return flags.SetNull, flags.ErrMySqlDB
|
||
|
}
|
||
|
if stockFIdr != nil {
|
||
|
usableFOld = decimal.RequireFromString(stockFIdr.UsableNum)
|
||
|
frozenFOld = decimal.RequireFromString(stockFIdr.FrozenNum)
|
||
|
}
|
||
|
if !flags.CheckSetting {
|
||
|
applogger.Debug("下单可用资产:%v", usableOld)
|
||
|
applogger.Debug("下单冻结资产:%v", frozenOld)
|
||
|
applogger.Debug("下单可用非资产:%v", usableFOld)
|
||
|
applogger.Debug("下单冻结非资产:%v", frozenFOld)
|
||
|
}
|
||
|
|
||
|
// 整理当前下单信息
|
||
|
serviceCost := decimal.RequireFromString(order.ServiceCost) // 订单手续费
|
||
|
orderNumber := decimal.RequireFromString(order.OrderNumber) // 订单数量
|
||
|
marketMoney := limitOrMarketPrice.Mul(orderNumber).Div(lever) // 订单金额(杠杆下单) = 订单数量 * 交易价格 / 杠杆
|
||
|
totalMoney := marketMoney.Add(serviceCost) // 订单总金额
|
||
|
order.MarketMoney = marketMoney.String() // 市值金额即为保证金
|
||
|
|
||
|
// TODO: 大宗(印尼股)交易检查订单ID是否存在,新增下单信息
|
||
|
var orderId string
|
||
|
if !CheckTypeStatus(order.Type) {
|
||
|
orderId, err = uo.VerifyBotStockIdnTradeOrderId(session)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v StockIdnOrderWriteDB.VerifyBotStockIdnTradeOrderId:%v", common.ErrShareIdn, err)
|
||
|
return flags.SetNull, err
|
||
|
}
|
||
|
trade := orders.BotStockIdnTrade(ctx, userId, orderId, order)
|
||
|
if err = uo.CreateBotStockIdnTrade(session, trade); err != nil {
|
||
|
applogger.Error("%v StockIdnOrderWriteDB.CreateBotStockIdnTrade:%v", common.ErrShareIdn, err)
|
||
|
return flags.SetNull, flags.ErrMySqlDB
|
||
|
}
|
||
|
} else {
|
||
|
orderId, err = uo.VerifyBotStockBlockTradeOrderId(session)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v StockIdnOrderWriteDB.VerifyBotStockBlockTradeOrderId:%v", common.ErrShareIdn, err)
|
||
|
return flags.SetNull, err
|
||
|
}
|
||
|
trade := orders.BotStockBlockTrade(ctx, userId, orderId, order)
|
||
|
if err = uo.CreateBotStockBlockTrade(session, trade); err != nil {
|
||
|
applogger.Error("%v StockIdnOrderWriteDB.CreateBotStockBlockTrade:%v", common.ErrShareIdn, err)
|
||
|
return flags.SetNull, flags.ErrMySqlDB
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 下单判定
|
||
|
residue := usableOld.Sub(totalMoney).Div(usableOld)
|
||
|
if usableOld.Cmp(totalMoney) <= 0 || residue.Cmp(utils.DecimalsStrInt()) <= 0 {
|
||
|
return flags.SetNull, flags.ErrPublicTow
|
||
|
}
|
||
|
|
||
|
var usableNew, frozenNew, usableFNew, frozenFNew decimal.Decimal
|
||
|
usableNew = usableOld.Sub(totalMoney) // 可用资产
|
||
|
frozenNew = frozenOld.Add(totalMoney) // 冻结资产
|
||
|
if order.StockId != flags.ShareIdnBasicUnit {
|
||
|
usableFNew = usableFOld.Add(orderNumber) // 可用非资产
|
||
|
frozenFNew = frozenFOld // 冻结非资产
|
||
|
}
|
||
|
|
||
|
// 检查用户订单下单资产
|
||
|
if usableNew.IsNegative() || usableNew.IsZero() {
|
||
|
return flags.SetNull, flags.ErrPublicTow
|
||
|
}
|
||
|
|
||
|
// 下单更新资产信息
|
||
|
stockIdrModel := orders.UpdateBotUserStockIdn(ctx, usableNew.String(), frozenNew.String())
|
||
|
err = uo.UpdateBotUserStockIdnByUserIdAndStockId(session, userId, flags.ShareIdnBasicUnit, stockIdrModel)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v StockIdnOrderWriteDB.UpdateBotUserStockIdnByUserIdAndStockId:%v", common.ErrShareIdn, err)
|
||
|
return flags.SetNull, flags.ErrMySqlDB
|
||
|
}
|
||
|
|
||
|
// 下单(新增|更新)非资产信息
|
||
|
if stockFIdr == nil {
|
||
|
stockFIDRModel := orders.CreateBotUserStockIdn(ctx, userId, order.StockId, usableFNew.String(), frozenFNew.String())
|
||
|
err = uo.CreateBotUserStockIdnFIRD(session, stockFIDRModel)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v StockIdnOrderWriteDB.CreateBotUserStockIdnFIRD:%v", common.ErrShareIdn, err)
|
||
|
return flags.SetNull, flags.ErrMySqlDB
|
||
|
}
|
||
|
} else {
|
||
|
stockFIDRModel := orders.UpdateBotUserStockIdn(ctx, usableFNew.String(), frozenFNew.String())
|
||
|
err = uo.UpdateBotUserStockIdnByUserIdAndStockId(session, userId, order.StockId, stockFIDRModel)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v StockIdnOrderWriteDB.UpdateBotUserStockIdnByUserIdAndStockId:%v", common.ErrShareIdn, err)
|
||
|
return flags.SetNull, flags.ErrMySqlDB
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if err = session.Commit(); err != nil {
|
||
|
applogger.Error("%v StockIdnOrderWriteDB.Commit:%v", common.ErrShareIdn, err)
|
||
|
return flags.SetNull, flags.ErrMySqlDB
|
||
|
}
|
||
|
|
||
|
return orderId, nil
|
||
|
}
|
||
|
|
||
|
// StockIdnOpenOrder
|
||
|
//
|
||
|
// @Description: 印尼股系统开仓
|
||
|
// @param ctx
|
||
|
// @param db
|
||
|
// @param userId
|
||
|
// @param orderId
|
||
|
// @param openPrice
|
||
|
// @param order
|
||
|
// @return error
|
||
|
func StockIdnOpenOrder(ctx context.Context, db *xorm.EngineGroup, userId int64, orderId, openPrice string, order structure.ShareOrder) error {
|
||
|
session := db.NewSession()
|
||
|
defer session.Close()
|
||
|
err := session.Begin()
|
||
|
if err != nil {
|
||
|
applogger.Error("%v StockIdnOpenOrder.NewSession:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
|
||
|
// 查询当前下单用户可用账户金额和冻结金额
|
||
|
var usable, frozen, usableNo, frozenNo decimal.Decimal
|
||
|
stockIdr, err := Uo.GetBotUserStockIdnByUserIdAndStockId(session, userId, flags.ShareIdnBasicUnit)
|
||
|
if err != nil || stockIdr == nil {
|
||
|
applogger.Error("%v StockIdnOpenOrder.GetBotUserStockIdnByUserIdAndStockId:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
usable = decimal.RequireFromString(stockIdr.UsableNum) // 用户可用资产
|
||
|
frozen = decimal.RequireFromString(stockIdr.FrozenNum) // 用户冻结资产
|
||
|
|
||
|
// 检查用户开仓资产
|
||
|
if usable.IsNegative() || frozen.IsNegative() {
|
||
|
return flags.ErrPublicThree
|
||
|
}
|
||
|
if order.StockId != flags.ShareIdnBasicUnit {
|
||
|
stockFIdr, err := Uo.GetBotUserStockIdnByUserIdAndStockId(session, userId, order.StockId)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v StockIdnOpenOrder.GetBotUserStockIdnByUserIdAndStockId:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
usableNo = decimal.RequireFromString(stockFIdr.UsableNum) // 用户非可用资产
|
||
|
frozenNo = decimal.RequireFromString(stockFIdr.FrozenNum) // 用户非冻结资产
|
||
|
}
|
||
|
if !flags.CheckSetting {
|
||
|
applogger.Debug("下单可用金额:%v", usable)
|
||
|
applogger.Debug("下单冻结金额:%v", frozen)
|
||
|
applogger.Debug("下单非可用金额:%v", usableNo)
|
||
|
applogger.Debug("下单非冻结金额:%v", frozenNo)
|
||
|
}
|
||
|
|
||
|
// 转换股票下单信息
|
||
|
orderNumber := decimal.RequireFromString(order.OrderNumber) // 下单股数
|
||
|
orderMoney := decimal.RequireFromString(order.MarketMoney) // 下单金额
|
||
|
serviceCost := decimal.RequireFromString(order.ServiceCost) // 下单手续费
|
||
|
totalMoney := orderMoney.Add(serviceCost) // 下单总金额 = (下单手续费 + 下单金额)
|
||
|
openOrderPrice := decimal.RequireFromString(openPrice) // 开盘价格
|
||
|
if !flags.CheckSetting {
|
||
|
applogger.Debug("下单订单数量:%v", orderNumber)
|
||
|
applogger.Debug("下单订单金额:%v", orderMoney)
|
||
|
applogger.Debug("下单订单手续费:%v", serviceCost)
|
||
|
applogger.Debug("下单订单总金额:%v", totalMoney)
|
||
|
}
|
||
|
|
||
|
// 手续费记录
|
||
|
openPriceNew := openOrderPrice.Mul(orderNumber).String() // 开仓手续费 = 开仓价格 * 股数 * 开仓手续费
|
||
|
cost, err := Uo.CalculateHandlingFeesShare(ctx, session, int(userId), flags.ShareIdnMarketType, flags.OpenBrokType, orderId, openPriceNew)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v StockIdnOpenOrder.CalculateHandlingFeesShare:%v", common.ErrShareIdn, err)
|
||
|
return err
|
||
|
}
|
||
|
openServiceCost := decimal.RequireFromString(cost) // 开仓手续费
|
||
|
openMarkerMoney := openOrderPrice.Mul(orderNumber).Div(decimal.RequireFromString(order.PryNum)) // 开仓订单金额 = 开仓价格 * 股数 / 杠杠
|
||
|
openTotalMoney := openMarkerMoney.Add(openServiceCost) // 开仓总金额 = 开仓订单金额 + 开仓手续费
|
||
|
floatPrice := totalMoney.Sub(openTotalMoney) // 计算容差 = 下单总额 - 开仓总额
|
||
|
if !flags.CheckSetting {
|
||
|
applogger.Debug("开仓订单价格:%v", openOrderPrice)
|
||
|
applogger.Debug("开仓手续费:%v", openServiceCost)
|
||
|
applogger.Debug("开仓总金额:%v", openTotalMoney)
|
||
|
applogger.Debug("开仓订单金额:%v", openMarkerMoney)
|
||
|
applogger.Debug("下单->开仓总金额容差值:%v", floatPrice)
|
||
|
}
|
||
|
|
||
|
var usableNew, frozenNew, usableNoNew, frozenNoNew decimal.Decimal
|
||
|
usableNew = usable.Add(floatPrice) // 可用资产(处理容差值)
|
||
|
frozenNew = frozen.Sub(totalMoney).Add(openMarkerMoney) // 冻结资产
|
||
|
if order.StockId != flags.ShareIdnBasicUnit {
|
||
|
usableNoNew = usableNo // 非可用资产
|
||
|
frozenNoNew = frozenNo // 非冻结资产
|
||
|
}
|
||
|
|
||
|
// 检查用户开仓资产
|
||
|
if frozenNew.IsNegative() || usableNew.IsNegative() {
|
||
|
return flags.ErrPublicThree
|
||
|
}
|
||
|
if !flags.CheckSetting {
|
||
|
applogger.Debug("下单后用户可用资产:%v", usableNew)
|
||
|
applogger.Debug("下单后用户冻结资产:%v", frozenNew)
|
||
|
}
|
||
|
|
||
|
// 处理资产信息
|
||
|
userStockIdr := orders.UpdateBotUserStockIdn(ctx, usableNew.String(), frozenNew.String())
|
||
|
if err = Uo.UpdateBotUserStockIdnByUserIdAndStockId(session, userId, flags.ShareIdnBasicUnit, userStockIdr); err != nil {
|
||
|
applogger.Error("%v StockIdnOpenOrder.IDR.UpdateBotUserStockIdnByUserIdAndStockId:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
|
||
|
// 更新非资产信息
|
||
|
if order.StockId != flags.ShareIdnBasicUnit {
|
||
|
userStockFIdr := orders.UpdateBotUserStockIdn(ctx, usableNoNew.String(), frozenNoNew.String())
|
||
|
if err = Uo.UpdateBotUserStockIdnByUserIdAndStockId(session, userId, order.StockId, userStockFIdr); err != nil {
|
||
|
applogger.Error("%v StockIdnOpenOrder.UpdateBotUserStockIdnByUserIdAndStockId:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 返佣记录|资金信息|资金详情信息
|
||
|
if err = Uo.ShareIdnRebateCalculation(ctx, session, int(userId), flags.ShareIdnMarketType, flags.OpenBrokType, flags.OpenMRebate, cost, orderId, order.Type); err != nil {
|
||
|
applogger.Error("%v StockIdnOpenOrder.ShareIdnRebateCalculation:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
|
||
|
// 处理订单信息(成交价|仓位|开仓时间|订单总金额|手续费|持仓状态)
|
||
|
if !CheckTypeStatus(order.Type) {
|
||
|
trade := orders.UpdateOpenBotStockIdnTrade(ctx, openPrice, orderNumber.String(), openTotalMoney.String(), openServiceCost.String(), openMarkerMoney.String())
|
||
|
if err = Uo.UpdateBotStockIdnTradeByOrderId(session, orderId, trade); err != nil {
|
||
|
applogger.Error("%v StockIdnOpenOrder.UpdateBotStockIdnTradeByOrderId:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
var list []models.BotUserStockIdnLog
|
||
|
qData0 := orders.CreatBotUserStockIdnLog(ctx, userId, flags.CostMoney, flags.ShareIdnBasicUnit, NegativeValue(openServiceCost.String()), orderId) // 资金变动明细表(开仓手续费)
|
||
|
qData1 := orders.CreatBotUserStockIdnLog(ctx, userId, flags.Freeze, flags.ShareIdnBasicUnit, NegativeValue(openMarkerMoney.String()), orderId) // 资金变动明细表(开仓保证金)
|
||
|
qData2 := orders.CreatBotUserStockIdnLog(ctx, userId, flags.ChangeInto, order.StockId, orderNumber.String(), orderId) // 资金变动明细表(非资产)
|
||
|
list = append(list, qData0, qData1, qData2)
|
||
|
|
||
|
// 批量写入数据信息
|
||
|
if err = Uo.CreatBotUserStockIdnLogList(session, list); err != nil {
|
||
|
applogger.Error("%v StockIdnOpenOrder.CreatBotUserStockIdnLogList:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
} else {
|
||
|
trade := orders.UpdateOpenBotStockBlockTrade(ctx, openPrice, orderNumber.String(), openTotalMoney.String(), openServiceCost.String(), openMarkerMoney.String())
|
||
|
if err = Uo.UpdateBotStockBlockTradeByOrderId(session, orderId, trade); err != nil {
|
||
|
applogger.Error("%v StockIdnOpenOrder.UpdateBotStockBlockTradeByOrderId:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
var list []models.BotUserStockBlockLog
|
||
|
qData0 := orders.CreatBotUserStockBlockLog(ctx, userId, flags.CostMoney, flags.ShareIdnBasicUnit, NegativeValue(openServiceCost.String()), orderId, order.Type) // 资金变动明细表(开仓手续费)
|
||
|
qData1 := orders.CreatBotUserStockBlockLog(ctx, userId, flags.Freeze, flags.ShareIdnBasicUnit, NegativeValue(openMarkerMoney.String()), orderId, order.Type) // 资金变动明细表(开仓保证金)
|
||
|
qData2 := orders.CreatBotUserStockBlockLog(ctx, userId, flags.ChangeInto, order.StockId, orderNumber.String(), orderId, order.Type) // 资金变动明细表(非资产)
|
||
|
list = append(list, qData0, qData1, qData2)
|
||
|
|
||
|
// 批量写入数据信息
|
||
|
if err = Uo.CreatBotUserStockBlockLogList(session, list); err != nil {
|
||
|
applogger.Error("%v StockIdnOpenOrder.CreatBotUserStockBlockLogList:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if err = session.Commit(); err != nil {
|
||
|
applogger.Error("%v StockIdnOpenOrder.Commit:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// StockIdnClosingOrder
|
||
|
//
|
||
|
// @Description: 印尼股系统平仓
|
||
|
// @param ctx
|
||
|
// @param db
|
||
|
// @param orderId
|
||
|
// @param price
|
||
|
// @param order
|
||
|
// @return error
|
||
|
func StockIdnClosingOrder(ctx context.Context, db *xorm.EngineGroup, orderId string, price string, order structure.ShareOrder) error {
|
||
|
session := db.NewSession()
|
||
|
defer session.Close()
|
||
|
err := session.Begin()
|
||
|
if err != nil {
|
||
|
applogger.Error("%v StockIdnClosingOrder.NewSession:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
|
||
|
// 查询订单信息
|
||
|
var userId int64
|
||
|
var dealPrice, orderNumber, totalAmount, serviceCost, marketMoney decimal.Decimal
|
||
|
if !CheckTypeStatus(order.Type) {
|
||
|
tread, err := Uo.GetBotStockIdnTradeByOrderIdOrStatus(session, orderId, flags.PositionStatus)
|
||
|
if err != nil || tread == nil {
|
||
|
applogger.Error("%v StockIdnClosingOrder.GetBotStockIdnTradeByOrderIdOrStatus:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
userId = int64(tread.UserId) // 用户Id
|
||
|
orderNumber = decimal.RequireFromString(tread.OrderNumber) // 下单数量
|
||
|
dealPrice = decimal.RequireFromString(tread.DealPrice) // 开仓价格
|
||
|
totalAmount = decimal.RequireFromString(tread.OrderMoney) // 开仓总金额
|
||
|
serviceCost = decimal.RequireFromString(tread.ServiceCost) // 开仓手续费
|
||
|
marketMoney = decimal.RequireFromString(tread.MarketMoney) // 开仓订单金额
|
||
|
} else {
|
||
|
tread, err := Uo.GetBotStockBlockTradeByOrderIdOrStatus(session, orderId, flags.PositionStatus)
|
||
|
if err != nil || tread == nil {
|
||
|
applogger.Error("%v StockIdnClosingOrder.GetBotStockBlockTradeByOrderIdOrStatus:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
userId = int64(tread.UserId) // 用户Id
|
||
|
orderNumber = decimal.RequireFromString(tread.OrderNumber) // 下单数量
|
||
|
dealPrice = decimal.RequireFromString(tread.DealPrice) // 开仓价格
|
||
|
totalAmount = decimal.RequireFromString(tread.OrderMoney) // 开仓总金额
|
||
|
serviceCost = decimal.RequireFromString(tread.ServiceCost) // 开仓手续费
|
||
|
marketMoney = decimal.RequireFromString(tread.MarketMoney) // 开仓订单金额
|
||
|
}
|
||
|
|
||
|
if !flags.CheckSetting {
|
||
|
applogger.Debug("下单开仓用户Id:%v", userId)
|
||
|
applogger.Debug("下单开仓开仓价格:%v", dealPrice)
|
||
|
applogger.Debug("下单开仓订单数量:%v", orderNumber)
|
||
|
applogger.Debug("下单开仓总金额:%v", totalAmount)
|
||
|
applogger.Debug("下单开仓手续费:%v", serviceCost)
|
||
|
applogger.Debug("下单开仓订单金额:%v", marketMoney)
|
||
|
}
|
||
|
|
||
|
// 查询当前下单用户可用账户金额和冻结金额
|
||
|
var usable, frozen, usableNo, frozenNo decimal.Decimal
|
||
|
userStockIdr, err := Uo.GetBotUserStockIdnByUserIdAndStockId(session, userId, flags.ShareIdnBasicUnit)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v StockIdnClosingOrder.GetBotUserStockByUserIdAndStockId:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
usable = decimal.RequireFromString(userStockIdr.UsableNum) // 用户可用资金
|
||
|
frozen = decimal.RequireFromString(userStockIdr.FrozenNum) // 用户非冻结资金
|
||
|
|
||
|
// 检查用户订单平仓资产
|
||
|
if usable.IsNegative() || frozen.IsNegative() {
|
||
|
return flags.ErrShareTow
|
||
|
}
|
||
|
|
||
|
// 查询当前下单用户可用非账户和冻结金额
|
||
|
if order.StockId != flags.ShareIdnBasicUnit {
|
||
|
userStockFIdr, err := Uo.GetBotUserStockIdnByUserIdAndStockId(session, userId, order.StockId)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v StockIdnClosingOrder.GetBotUserStockIdnByUserIdAndStockId:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
usableNo = decimal.RequireFromString(userStockFIdr.UsableNum) // 用户非可用资金
|
||
|
frozenNo = decimal.RequireFromString(userStockFIdr.FrozenNum) // 用户非冻结资金
|
||
|
}
|
||
|
if !flags.CheckSetting {
|
||
|
applogger.Debug("下单可用金额:%v", usable)
|
||
|
applogger.Debug("下单冻结金额:%v", frozen)
|
||
|
applogger.Debug("下单非可用金额:%v", usableNo)
|
||
|
applogger.Debug("下单非冻结金额:%v", frozenNo)
|
||
|
}
|
||
|
|
||
|
// 手续费处理
|
||
|
closePrice := decimal.RequireFromString(price) // 平仓价格
|
||
|
cloePriceCost := closePrice.Mul(orderNumber).String() // 平仓手续费 = 平仓价格 * 股数 * 手续费比例
|
||
|
cost, err := Uo.CalculateHandlingFeesShare(ctx, session, int(userId), flags.ShareIdnMarketType, flags.ClosingBrokType, orderId, cloePriceCost)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v StockIdnClosingOrder.CalculateHandlingFeesShare:%v", common.ErrShareIdn, 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)
|
||
|
case flags.TradeTypeSell: // 买跌
|
||
|
subPrice = dealPrice.Sub(closePrice)
|
||
|
resultPrice = subPrice.Mul(orderNumber)
|
||
|
default:
|
||
|
}
|
||
|
|
||
|
// TODO: 判定亏损不能超过 = 保证金 + 平仓手续费
|
||
|
if resultPrice.IsNegative() {
|
||
|
amountLoss := marketMoney.Sub(closeServiceCost)
|
||
|
if resultPrice.Abs().Cmp(amountLoss) >= 0 {
|
||
|
resultPrice = amountLoss.Neg()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 用户资产账户
|
||
|
usableNew = usable.Add(resultPrice).Sub(closeServiceCost).Add(marketMoney) // 可用资产 = 原可用资产 + ((正负)盈亏) - 平仓手续费 + 开仓订单金额
|
||
|
if frozen.Cmp(marketMoney) == -1 {
|
||
|
frozenNew = frozen.Sub(frozen) // 冻结资产
|
||
|
} else {
|
||
|
frozenNew = frozen.Sub(marketMoney) // 冻结资产
|
||
|
}
|
||
|
|
||
|
// 用户非资产账户
|
||
|
if order.StockId != flags.ShareIdnBasicUnit {
|
||
|
usableNewNo = usableNo.Sub(orderNumber) // 可用非资产 = 原可用非资产 - 下单股数
|
||
|
frozenNewNo = frozenNo // 可用非冻结资产
|
||
|
}
|
||
|
|
||
|
// 检查用户平仓资产
|
||
|
if frozenNew.IsNegative() || usableNewNo.IsNegative() {
|
||
|
return flags.ErrShareTow
|
||
|
}
|
||
|
if !flags.CheckSetting {
|
||
|
applogger.Debug("可用资产:%v", usableNew)
|
||
|
applogger.Debug("冻结资产:%v", frozenNew)
|
||
|
applogger.Debug("可用非资产:%v", usableNewNo)
|
||
|
applogger.Debug("冻结非资产:%v", frozenNewNo)
|
||
|
}
|
||
|
|
||
|
// 平仓(处理资产表(资产))
|
||
|
userStockIDR := orders.UpdateBotUserStockIdn(ctx, usableNew.String(), frozenNew.String())
|
||
|
if err = Uo.UpdateBotUserStockIdnByUserIdAndStockId(session, userId, flags.ShareIdnBasicUnit, userStockIDR); err != nil {
|
||
|
applogger.Error("%v StockIdnClosingOrder.USD.UpdateBotUserStockIdnByUserIdAndStockId:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
|
||
|
// 平仓(处理资产表(非资产))
|
||
|
if order.StockId != flags.ShareIdnBasicUnit {
|
||
|
userStockFIDR := orders.UpdateBotUserStockIdn(ctx, usableNewNo.String(), frozenNewNo.String())
|
||
|
if err = Uo.UpdateBotUserStockIdnByUserIdAndStockId(session, userId, order.StockId, userStockFIDR); err != nil {
|
||
|
applogger.Error("%v StockIdnClosingOrder.UpdateBotUserStockIdnByUserIdAndStockId:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 平仓(返佣记录表|资产表|资金变动表)
|
||
|
if err = Uo.ShareIdnRebateCalculation(ctx, session, int(userId), flags.ShareIdnMarketType, flags.ClosingBrokType, flags.CloseMRebate, cost, orderId, order.Type); err != nil {
|
||
|
applogger.Error("%v StockIdnClosingOrder.ShareIdnRebateCalculation:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
|
||
|
// 平仓(处理订单信息(平仓价|保证金|平仓|订单总金额|平仓手续费|完成订单))
|
||
|
if !CheckTypeStatus(order.Type) {
|
||
|
trade := orders.UpdateCloseBotStockIdnTrade(ctx, price, cost)
|
||
|
if err = Uo.UpdateBotStockIdnTradeByOrderId(session, orderId, trade); err != nil {
|
||
|
applogger.Error("%v StockIdnClosingOrder.UpdateBotStockIdnTradeByOrderId:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
|
||
|
var list []models.BotUserStockIdnLog
|
||
|
qData0 := orders.CreatBotUserStockIdnLog(ctx, userId, flags.Thaw, flags.ShareIdnBasicUnit, marketMoney.String(), orderId) // 平仓(资金变动明细表(开仓保证金))
|
||
|
qData1 := orders.CreatBotUserStockIdnLog(ctx, userId, flags.CostMoney, flags.ShareIdnBasicUnit, NegativeValue(closeServiceCost.String()), orderId) // 平仓(资金变动明细表(平仓手续费))
|
||
|
qData2 := orders.CreatBotUserStockIdnLog(ctx, userId, flags.TransferOut, order.StockId, NegativeValue(orderNumber.String()), orderId) // 平仓(资金变动明细表(非资产))
|
||
|
list = append(list, qData0, qData1, qData2)
|
||
|
// 平仓(资金变动明细表(正负盈亏))
|
||
|
if resultPrice.IsNegative() {
|
||
|
qData3 := orders.CreatBotUserStockIdnLog(ctx, userId, flags.TransferOut, flags.ShareIdnBasicUnit, resultPrice.String(), orderId)
|
||
|
list = append(list, qData3)
|
||
|
} else {
|
||
|
qData4 := orders.CreatBotUserStockIdnLog(ctx, userId, flags.ChangeInto, flags.ShareIdnBasicUnit, resultPrice.String(), orderId)
|
||
|
list = append(list, qData4)
|
||
|
}
|
||
|
// 平仓(批量写入交易订单日志信息)
|
||
|
if err = Uo.CreatBotUserStockIdnLogList(session, list); err != nil {
|
||
|
applogger.Error("%v StockIdnClosingOrder.CreatBotUserStockIdnLogList:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
} else {
|
||
|
trade := orders.UpdateCloseBotStockBlockTrade(ctx, price, cost)
|
||
|
if err = Uo.UpdateBotStockBlockTradeByOrderId(session, orderId, trade); err != nil {
|
||
|
applogger.Error("%v StockIdnClosingOrder.UpdateBotStockBlockTradeByOrderId:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
|
||
|
var list []models.BotUserStockBlockLog
|
||
|
qData0 := orders.CreatBotUserStockBlockLog(ctx, userId, flags.Thaw, flags.ShareIdnBasicUnit, marketMoney.String(), orderId, order.Type) // 平仓(资金变动明细表(开仓保证金))
|
||
|
qData1 := orders.CreatBotUserStockBlockLog(ctx, userId, flags.CostMoney, flags.ShareIdnBasicUnit, NegativeValue(closeServiceCost.String()), orderId, order.Type) // 平仓(资金变动明细表(平仓手续费))
|
||
|
qData2 := orders.CreatBotUserStockBlockLog(ctx, userId, flags.TransferOut, order.StockId, NegativeValue(orderNumber.String()), orderId, order.Type) // 平仓(资金变动明细表(非资产))
|
||
|
list = append(list, qData0, qData1, qData2)
|
||
|
// 平仓(资金变动明细表(正负盈亏))
|
||
|
if resultPrice.IsNegative() {
|
||
|
qData3 := orders.CreatBotUserStockBlockLog(ctx, userId, flags.TransferOut, flags.ShareIdnBasicUnit, resultPrice.String(), orderId, order.Type)
|
||
|
list = append(list, qData3)
|
||
|
} else {
|
||
|
qData4 := orders.CreatBotUserStockBlockLog(ctx, userId, flags.ChangeInto, flags.ShareIdnBasicUnit, resultPrice.String(), orderId, order.Type)
|
||
|
list = append(list, qData4)
|
||
|
}
|
||
|
// 平仓(批量写入交易订单日志信息)
|
||
|
if err = Uo.CreatBotUserStockBlockLogList(session, list); err != nil {
|
||
|
applogger.Error("%v StockIdnClosingOrder.CreatBotUserStockBlockLogList:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if err = session.Commit(); err != nil {
|
||
|
applogger.Error("%v StockClosingOrder.Commit:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// UpdateBotStockIdnCancelByOrderId
|
||
|
//
|
||
|
// @Description: 印尼股撤单
|
||
|
// @receiver uo
|
||
|
// @param ctx
|
||
|
// @param orderId
|
||
|
// @return bool
|
||
|
// @return error
|
||
|
func (uo *userOrderRepo) UpdateBotStockIdnCancelByOrderId(ctx context.Context, orderId string, typeStatus int64) (bool, error) {
|
||
|
session := uo.data.mysqlDB.NewSession()
|
||
|
defer session.Close()
|
||
|
err := session.Begin()
|
||
|
if err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnCancelByOrderId.Begin:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrMySqlDB
|
||
|
}
|
||
|
|
||
|
// 获取订单信息
|
||
|
var userId int64
|
||
|
var stockId string
|
||
|
var marketMoneyOld, serviceCostOld, orderNumber decimal.Decimal
|
||
|
if !CheckTypeStatus(typeStatus) {
|
||
|
stockTrade, err := uo.GetBotStockIdnTradeByOrderId(session, orderId)
|
||
|
if err != nil || stockTrade == nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnCancelByOrderId.GetBotStockIdnTradeByOrderId:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrMySqlDB
|
||
|
}
|
||
|
marketMoneyOld = decimal.RequireFromString(stockTrade.MarketMoney) // 订单Id
|
||
|
serviceCostOld = decimal.RequireFromString(stockTrade.ServiceCost) // 手续费
|
||
|
orderNumber = decimal.RequireFromString(stockTrade.OrderNumber) // 订单数量
|
||
|
userId = int64(stockTrade.UserId) // 用户Id
|
||
|
stockId = stockTrade.StockId // 下单交易对
|
||
|
} else {
|
||
|
stockTrade, err := uo.GetBotStockBlockTradeByOrderId(session, orderId)
|
||
|
if err != nil || stockTrade == nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnCancelByOrderId.GetBotStockBlockTradeByOrderId:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrMySqlDB
|
||
|
}
|
||
|
marketMoneyOld = decimal.RequireFromString(stockTrade.MarketMoney) // 订单Id
|
||
|
serviceCostOld = decimal.RequireFromString(stockTrade.ServiceCost) // 手续费
|
||
|
orderNumber = decimal.RequireFromString(stockTrade.OrderNumber) // 订单数量
|
||
|
userId = int64(stockTrade.UserId) // 用户Id
|
||
|
stockId = stockTrade.StockId // 下单交易对
|
||
|
}
|
||
|
|
||
|
// 获取用户资产信息
|
||
|
var usable, frozen, usableNo, frozenNo decimal.Decimal
|
||
|
stockIdr, err := uo.GetBotUserStockIdnByUserIdAndStockId(session, userId, flags.ShareIdnBasicUnit)
|
||
|
if err != nil || stockIdr == nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnCancelByOrderId.IDR.GetBotUserStockIdnByUserIdAndStockId:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrMySqlDB
|
||
|
}
|
||
|
usable = decimal.RequireFromString(stockIdr.UsableNum) // 用户账户可用资产
|
||
|
frozen = decimal.RequireFromString(stockIdr.FrozenNum) // 用户账户冻结资产
|
||
|
|
||
|
// 检查用户订单撤单资产
|
||
|
if frozen.IsNegative() || usable.IsNegative() {
|
||
|
return false, flags.ErrShareThree
|
||
|
}
|
||
|
if stockId != flags.ShareIdnBasicUnit {
|
||
|
stockFUsd, err := uo.GetBotUserStockIdnByUserIdAndStockId(session, userId, stockId)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnCancelByOrderId.GetBotUserStockIdnByUserIdAndStockId:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrPublicFour
|
||
|
}
|
||
|
usableNo = decimal.RequireFromString(stockFUsd.UsableNum) // 用户非账户可用资产
|
||
|
frozenNo = decimal.RequireFromString(stockFUsd.FrozenNum) // 用户非账户冻结资产
|
||
|
}
|
||
|
if !flags.CheckSetting {
|
||
|
applogger.Debug("用户原始可用资金:%v", usable)
|
||
|
applogger.Debug("用户原始冻结资金:%v", frozen)
|
||
|
applogger.Debug("用户原始可用非资金:%v", usableNo)
|
||
|
applogger.Debug("用户原始冻结非资金:%v", frozenNo)
|
||
|
}
|
||
|
|
||
|
// 更新订单信息
|
||
|
var entrustKey, userKey, adminKey string
|
||
|
if !CheckTypeStatus(typeStatus) {
|
||
|
botStockTrade := orders.BotStockIdnCancelByOrderId(ctx)
|
||
|
if err = uo.UpdateBotStockIdnTradeByOrderId(session, orderId, botStockTrade); err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnCancelByOrderId.IDR.UpdateBotStockIdnTradeByOrderId:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrMySqlDB
|
||
|
}
|
||
|
// 缓存Key
|
||
|
entrustKey = setting.MarketShareIdnEntrust
|
||
|
userKey = setting.ShareIdnSubscribe
|
||
|
adminKey = setting.AdminShareIdnSubscribe
|
||
|
} else {
|
||
|
botStockTrade := orders.BotStockBlockCancelByOrderId(ctx)
|
||
|
if err = uo.UpdateBotStockBlockTradeByOrderId(session, orderId, botStockTrade); err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnCancelByOrderId.IDR.UpdateBotStockBlockTradeByOrderId:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrMySqlDB
|
||
|
}
|
||
|
// 缓存Key
|
||
|
entrustKey = setting.MarketShareBlkEntrust
|
||
|
userKey = setting.ShareBlkSubscribe
|
||
|
adminKey = setting.AdminShareBlkSubscribe
|
||
|
}
|
||
|
|
||
|
// Operational Spot Asset Table
|
||
|
totalMoney := marketMoneyOld.Add(serviceCostOld) // 订单总金额
|
||
|
// update total asset data
|
||
|
usableNew := usable.Add(totalMoney) // 用户总资产
|
||
|
frozenNew := frozen.Sub(totalMoney) // 用户冻结资产
|
||
|
usableNoNew := usableNo.Sub(orderNumber) // 用户非可用资产
|
||
|
frozenNoNew := frozenNo // 用户非冻结资产
|
||
|
if !flags.CheckSetting {
|
||
|
applogger.Debug("用户撤单可用总资产:%v", usableNew)
|
||
|
applogger.Debug("用户撤单冻结总资产:%v", frozenNew)
|
||
|
applogger.Debug("用户非撤单可用总资产:%v", usableNoNew)
|
||
|
applogger.Debug("用户非撤单冻结总资产:%v", frozenNoNew)
|
||
|
}
|
||
|
|
||
|
// 检查用户订单撤单资产
|
||
|
if frozenNew.IsNegative() || usableNoNew.IsNegative() {
|
||
|
return false, flags.ErrShareThree
|
||
|
}
|
||
|
|
||
|
// 更新资产信息和非资产信息
|
||
|
userStockIDR := orders.UpdateBotUserStockIdn(ctx, usableNew.String(), frozenNew.String())
|
||
|
if err = uo.UpdateBotUserStockIdnByUserIdAndStockId(session, userId, flags.ShareIdnBasicUnit, userStockIDR); err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnCancelByOrderId.UpdateBotUserStockIdnByUserIdAndStockId:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrMySqlDB
|
||
|
}
|
||
|
if stockId != flags.ShareIdnBasicUnit {
|
||
|
userStockFIdn := orders.UpdateBotUserStockIdn(ctx, usableNoNew.String(), frozenNoNew.String())
|
||
|
if err = uo.UpdateBotUserStockIdnByUserIdAndStockId(session, userId, stockId, userStockFIdn); err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnCancelByOrderId.UpdateBotUserStockIdnByUserIdAndStockId:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrMySqlDB
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 删除订单缓存列表
|
||
|
if err = Reds.HDel(context.Background(), entrustKey, orderId).Err(); err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnCancelByOrderId.HDel:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrCacheDB
|
||
|
}
|
||
|
|
||
|
// 更新用户订阅订单缓存列表
|
||
|
userSubKey := virtual.OrderIdListKey(userKey, userId)
|
||
|
if err = share.UpdateShareIdnHashByOrderId(Reds, orderId, userSubKey, flags.Cancel); err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnCancelByOrderId.%v:%v", common.ErrShareIdn, userKey, err)
|
||
|
return false, flags.ErrCacheDB
|
||
|
}
|
||
|
|
||
|
// 更新管理员订阅订单缓存列表
|
||
|
if err = UpdateShareIdnSubscribeHashStatusByOrderId(orderId, adminKey, flags.Cancel, flags.SetNull); err != nil {
|
||
|
applogger.Error("%v UpdateBotContractCancelByOrderId.%v:%v", common.ErrShareIdn, adminKey, err)
|
||
|
return false, flags.ErrCacheDB
|
||
|
}
|
||
|
|
||
|
if err = session.Commit(); err != nil {
|
||
|
applogger.Error("%v UpdateBotContractCancelByOrderId.Commit:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrMySqlDB
|
||
|
}
|
||
|
|
||
|
return true, nil
|
||
|
}
|
||
|
|
||
|
// UpdateBotStockIdnStopByOrderId
|
||
|
//
|
||
|
// @Description: 印尼股设置止盈止损
|
||
|
// @receiver uo
|
||
|
// @param ctx
|
||
|
// @param order
|
||
|
// @return bool
|
||
|
// @return error
|
||
|
func (uo *userOrderRepo) UpdateBotStockIdnStopByOrderId(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 UpdateBotStockIdnStopByOrderId.NewSession:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrMySqlDB
|
||
|
}
|
||
|
|
||
|
// 设置止盈止损
|
||
|
var userId int64
|
||
|
if order.StopType == 1 {
|
||
|
// 股票下单信息
|
||
|
checkBool, stopWinPrice, stopLossPrice, err := uo.UpdateVoteStopType(order)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnStopByOrderId.UpdateVoteStopType:%v", common.ErrShareIdn, err)
|
||
|
return false, err
|
||
|
}
|
||
|
if !flags.CheckSetting {
|
||
|
applogger.Debug("当前止盈止损数据:%v,%v,%v", checkBool, stopWinPrice, stopLossPrice)
|
||
|
}
|
||
|
|
||
|
// 设置止盈止损判定
|
||
|
var tradeType int
|
||
|
var limitOrMarketPrice decimal.Decimal
|
||
|
if !CheckTypeStatus(order.Type) {
|
||
|
trade, err := uo.GetBotStockIdnTradeByOrderIdOrStatus(session, order.OrderId, flags.PositionStatus)
|
||
|
if err != nil || trade == nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnStopByOrderId.GetBotStockIdnTradeByOrderIdOrStatus:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrShareFour
|
||
|
}
|
||
|
tradeType = trade.TradeType
|
||
|
userId = int64(trade.UserId)
|
||
|
// 下单判定设置(限价|市价|开仓价)
|
||
|
limitOrMarketPrice, err = uo.UpdateShareIdnVoteDealType(trade)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnStopByOrderId.UpdateShareIdnVoteDealType:%v", common.ErrShareIdn, err)
|
||
|
return false, err
|
||
|
}
|
||
|
} else {
|
||
|
trade, err := uo.GetBotStockBlockTradeByOrderIdOrStatus(session, order.OrderId, flags.PositionStatus)
|
||
|
if err != nil || trade == nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnStopByOrderId.GetBotStockBlockTradeByOrderIdOrStatus:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrShareFour
|
||
|
}
|
||
|
tradeType = trade.TradeType
|
||
|
userId = int64(trade.UserId)
|
||
|
// 下单判定设置(限价|市价|开仓价)
|
||
|
limitOrMarketPrice, err = uo.UpdateShareBlockVoteDealType(trade)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnStopByOrderId.UpdateShareBlockVoteDealType:%v", common.ErrShareIdn, err)
|
||
|
return false, err
|
||
|
}
|
||
|
}
|
||
|
if !flags.CheckSetting {
|
||
|
applogger.Debug("当前开仓价格:%v", limitOrMarketPrice)
|
||
|
}
|
||
|
|
||
|
// 下单判定设置(买涨|买跌)
|
||
|
if err = uo.VoteTradeType(int64(tradeType), stopWinPrice, stopLossPrice, limitOrMarketPrice, checkBool); err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnStopByOrderId.VoteTradeType:%v", common.ErrShareIdn, err)
|
||
|
return false, err
|
||
|
}
|
||
|
} else {
|
||
|
order.StopLossPrice = decimal.Zero.String()
|
||
|
order.StopWinPrice = decimal.Zero.String()
|
||
|
}
|
||
|
|
||
|
// TODO: 获取存在IPO未支付订单的用户
|
||
|
userIdMap, _ := GetBotUserArrears(ctx)
|
||
|
_, ok := userIdMap[userId]
|
||
|
if ok {
|
||
|
return false, flags.ErrPublicServe
|
||
|
}
|
||
|
|
||
|
// 更新订单表
|
||
|
var positionKey string
|
||
|
if !CheckTypeStatus(order.Type) {
|
||
|
botStockIdnTrade := orders.BotStockIdnStopByOrderId(ctx, order)
|
||
|
if err = uo.UpdateBotStockIdnTradeByOrderId(session, order.OrderId, botStockIdnTrade); err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnStopByOrderId.UpdateBotStockIdnTradeByOrderId:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrMySqlDB
|
||
|
}
|
||
|
positionKey = setting.MarketShareIdnPosition
|
||
|
} else {
|
||
|
botStockIdnTrade := orders.BotStockBlockStopByOrderId(ctx, order)
|
||
|
if err = uo.UpdateBotStockBlockTradeByOrderId(session, order.OrderId, botStockIdnTrade); err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnStopByOrderId.UpdateBotStockBlockTradeByOrderId:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrMySqlDB
|
||
|
}
|
||
|
positionKey = setting.MarketShareBlkPosition
|
||
|
}
|
||
|
|
||
|
// 修改挂单缓存队列
|
||
|
if err = share.UpdateShareIdnStopByOrderId(Reds, order, positionKey, flags.Position); err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnStopByOrderId.UpdateShareIdnStopByOrderId:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrCacheDB
|
||
|
}
|
||
|
|
||
|
if err = session.Commit(); err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnStopByOrderId.Commit:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrMySqlDB
|
||
|
}
|
||
|
|
||
|
return true, nil
|
||
|
}
|
||
|
|
||
|
// UpdateBotStockIdnClosingByOrderId
|
||
|
//
|
||
|
// @Description: 印尼股用户平仓
|
||
|
// @receiver uo
|
||
|
// @param ctx
|
||
|
// @param orderId
|
||
|
// @return bool
|
||
|
// @return error
|
||
|
func (uo *userOrderRepo) UpdateBotStockIdnClosingByOrderId(ctx context.Context, orderId string, typeStatus int64) (bool, error) {
|
||
|
// 下单判定-冷静期停止所有交易
|
||
|
if CheckGlobalTread(flags.IdnMarket) {
|
||
|
return false, flags.ErrStopTread
|
||
|
}
|
||
|
|
||
|
// 1、查询持仓缓存列表数据并清理对应缓存
|
||
|
var positionKey, userKey, adminKey string
|
||
|
if !CheckTypeStatus(typeStatus) {
|
||
|
positionKey = setting.MarketShareIdnPosition
|
||
|
userKey = setting.ShareIdnSubscribe
|
||
|
adminKey = setting.AdminShareIdnSubscribe
|
||
|
} else {
|
||
|
positionKey = setting.MarketShareBlkPosition
|
||
|
userKey = setting.ShareBlkSubscribe
|
||
|
adminKey = setting.AdminShareBlkSubscribe
|
||
|
}
|
||
|
var entrustCache *share.ShareIdnTallyCache
|
||
|
entrust, err := Reds.HGet(context.Background(), positionKey, orderId).Result()
|
||
|
if err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnClosingByOrderId.HGet:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrShareFive
|
||
|
}
|
||
|
var entrustJson share.ShareIdnTallyCache
|
||
|
if err = json.Unmarshal([]byte(entrust), &entrustJson); err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnClosingByOrderId.Unmarshal:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrCacheDB
|
||
|
}
|
||
|
|
||
|
if orderId == entrustJson.OrderId {
|
||
|
entrustCache = &entrustJson
|
||
|
}
|
||
|
|
||
|
if entrustCache == nil {
|
||
|
return false, flags.ErrShareFive
|
||
|
}
|
||
|
|
||
|
// TODO: 获取存在IPO未支付订单的用户
|
||
|
userIdMap, _ := GetBotUserArrears(ctx)
|
||
|
_, ok := userIdMap[entrustJson.UserId]
|
||
|
if ok {
|
||
|
return false, flags.ErrPublicServe
|
||
|
}
|
||
|
|
||
|
// 市场设置交易时间(T+0,T+1,T+2s......)
|
||
|
if !CheckShareSystemTime(entrustCache.ClosingTime) {
|
||
|
return false, flags.ErrStopTread
|
||
|
}
|
||
|
if !flags.CheckSetting {
|
||
|
applogger.Debug("手动平仓:%v", entrustCache)
|
||
|
}
|
||
|
|
||
|
// 2、获取当前最新价格
|
||
|
var closingPrice decimal.Decimal
|
||
|
subKey := publicData.SymbolCache(flags.Idn, entrustCache.Symbol, flags.TradeTypePrice)
|
||
|
closingPrice, err = uo.GetShareIdnTheLatestPrice(subKey, entrustCache.Order.TradeType)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnClosingByOrderId.GetShareIdnTheLatestPrice:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrStopTread
|
||
|
}
|
||
|
|
||
|
// 3、平仓处理
|
||
|
if err = StockIdnClosingOrder(ctx, Msql, orderId, closingPrice.String(), entrustCache.Order); err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnClosingByOrderId.StockIdnClosingOrder:%v", common.ErrShareIdn, err)
|
||
|
return false, err
|
||
|
}
|
||
|
|
||
|
// 4、清理持仓订单信息
|
||
|
var removedCount int64
|
||
|
removedCount, err = Reds.HDel(context.Background(), positionKey, orderId).Result()
|
||
|
if err != nil || removedCount == 0 {
|
||
|
applogger.Error("%v UpdateBotStockIdnClosingByOrderId.HDel:%v", common.ErrShareIdn, err)
|
||
|
return false, flags.ErrCacheDB
|
||
|
}
|
||
|
|
||
|
// 5、平仓更新订阅缓存订单状态
|
||
|
userSubKey := virtual.OrderIdListKey(userKey, entrustCache.UserId)
|
||
|
if err = UpdateShareIdnSubscribeHashStatusByOrderId(orderId, userSubKey, flags.Close, flags.SetNull); err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnClosingByOrderId.%v:%v", common.ErrShareIdn, userKey, err)
|
||
|
return false, flags.ErrCacheDB
|
||
|
}
|
||
|
|
||
|
// 6、平仓更新管理员订阅缓存订单状态
|
||
|
if err = UpdateShareIdnSubscribeHashStatusByOrderId(orderId, adminKey, flags.Close, flags.SetNull); err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnClosingByOrderId.%v:%v", common.ErrShareIdn, adminKey, err)
|
||
|
return false, flags.ErrCacheDB
|
||
|
}
|
||
|
|
||
|
return true, nil
|
||
|
}
|
||
|
|
||
|
// UpdateBotStockIdnAllClosingByOrderId
|
||
|
//
|
||
|
// @Description: 印尼股用户一键平仓
|
||
|
// @receiver uo
|
||
|
// @param ctx
|
||
|
// @param userId
|
||
|
// @return error
|
||
|
func (uo *userOrderRepo) UpdateBotStockIdnAllClosingByOrderId(ctx context.Context, userId int64) error {
|
||
|
// 下单判定-冷静期停止所有交易
|
||
|
if CheckGlobalTread(flags.IdnMarket) {
|
||
|
return flags.ErrStopTread
|
||
|
}
|
||
|
|
||
|
// TODO: 获取存在IPO未支付订单的用户
|
||
|
userIdMap, _ := GetBotUserArrears(ctx)
|
||
|
_, isOk := userIdMap[userId]
|
||
|
if isOk {
|
||
|
return flags.ErrPublicServe
|
||
|
}
|
||
|
|
||
|
// 1、查询当前用户所有订单
|
||
|
orderMap, err := uo.GetBotStockIdnTradeByUserId(userId)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnAllClosingByOrderId.GetBotStockIdnTradeByUserId:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrMySqlDB
|
||
|
}
|
||
|
|
||
|
// 2、查询持仓缓存列表数据-1、清理持仓列表缓存 2、处理平仓数据 3、清理订单ID缓存列表
|
||
|
entrust, err := Reds.HGetAll(context.Background(), setting.MarketShareIdnPosition).Result()
|
||
|
if err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnAllClosingByOrderId.HGetAll:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrShareFive
|
||
|
}
|
||
|
|
||
|
// 3、循环检查股票交易对最新价格(有一个查询不到既不能平仓)
|
||
|
var entrustList []share.ShareIdnTallyCache
|
||
|
closePriceMap := make(map[string]decimal.Decimal)
|
||
|
for key, value := range entrust {
|
||
|
var entrustJson share.ShareIdnTallyCache
|
||
|
if err = json.Unmarshal([]byte(value), &entrustJson); err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnAllClosingByOrderId.Unmarshal:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrStopTread
|
||
|
}
|
||
|
_, ok := orderMap[entrustJson.OrderId]
|
||
|
if ok {
|
||
|
var closingPrice decimal.Decimal
|
||
|
subKey := publicData.SymbolCache(flags.Idn, entrustJson.Symbol, flags.TradeTypePrice)
|
||
|
closingPrice, err = uo.GetShareIdnTheLatestPrice(subKey, entrustJson.Order.TradeType)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnAllClosingByOrderId.GetShareIdnTheLatestPrice:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrStopTread
|
||
|
}
|
||
|
if !flags.CheckSetting {
|
||
|
applogger.Debug("订阅Key:%v,最新价格:%v,订单ID:%v", subKey, closingPrice, entrustJson.OrderId)
|
||
|
}
|
||
|
|
||
|
closePriceMap[key] = closingPrice
|
||
|
entrustList = append(entrustList, entrustJson)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 4、股票一键平仓
|
||
|
for _, value := range entrustList {
|
||
|
closePrice, ok := closePriceMap[value.OrderId]
|
||
|
if ok {
|
||
|
// 平仓
|
||
|
if err = StockIdnClosingOrder(ctx, uo.data.mysqlDB, value.OrderId, closePrice.String(), value.Order); err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnAllClosingByOrderId.StockIdnClosingOrder:%v", common.ErrShareIdn, err)
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// 清理持仓缓存列表
|
||
|
var removedCount int64
|
||
|
removedCount, err = Reds.HDel(context.Background(), setting.MarketShareIdnPosition, value.OrderId).Result()
|
||
|
if err != nil || removedCount == 0 {
|
||
|
applogger.Error("%v UpdateBotStockIdnAllClosingByOrderId.HDel:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrCacheDB
|
||
|
}
|
||
|
|
||
|
// 平仓更新用户订阅订单状态
|
||
|
userSubKey := virtual.OrderIdListKey(setting.ShareIdnSubscribe, value.UserId)
|
||
|
if err = UpdateShareIdnSubscribeHashStatusByOrderId(value.OrderId, userSubKey, flags.Close, flags.SetNull); err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnAllClosingByOrderId.UpdateShareIdnSubscribeHashStatusByOrderId:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrCacheDB
|
||
|
}
|
||
|
|
||
|
// 平仓更新管理员订阅订单状态
|
||
|
if err = UpdateShareIdnSubscribeHashStatusByOrderId(value.OrderId, setting.AdminShareIdnSubscribe, flags.Close, flags.SetNull); err != nil {
|
||
|
applogger.Error("%v UpdateBotStockIdnAllClosingByOrderId.UpdateShareIdnSubscribeHashStatusByOrderId:%v", common.ErrShareIdn, err)
|
||
|
return flags.ErrCacheDB
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// GetBotStockIdnTradeByUserId
|
||
|
//
|
||
|
// @Description:
|
||
|
// @receiver uo
|
||
|
// @param ctx
|
||
|
// @param userId
|
||
|
// @return map[string]string
|
||
|
// @return error
|
||
|
func (uo *userOrderRepo) GetBotStockIdnTradeByUserId(userId int64) (map[string]string, error) {
|
||
|
var botStockIdnTrade []models.BotStockIdnTrade
|
||
|
if err := uo.data.mysqlDB.Table(flags.BotStockIdnTrade).
|
||
|
Where("user_id = ?", userId).
|
||
|
Where("status = 1").
|
||
|
Find(&botStockIdnTrade); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
botMap := make(map[string]string)
|
||
|
for _, value := range botStockIdnTrade {
|
||
|
botMap[value.OrderId] = value.OrderId
|
||
|
}
|
||
|
|
||
|
return botMap, nil
|
||
|
}
|
||
|
|
||
|
// GetShareIdnTheLatestPrice
|
||
|
//
|
||
|
// @Description:
|
||
|
// @receiver uo
|
||
|
// @param ctx
|
||
|
// @param subKey
|
||
|
// @param tradeType
|
||
|
// @return decimal.Decimal
|
||
|
// @return error
|
||
|
func (uo *userOrderRepo) GetShareIdnTheLatestPrice(subKey string, tradeType int64) (decimal.Decimal, error) {
|
||
|
priceNew, err := share.ShareIdnSubMarketPrice(subKey)
|
||
|
if err != nil {
|
||
|
applogger.Error("%v GetShareIdnTheLatestPrice.ShareIdnSubMarketPrice:%v", common.ErrShareIdn, err)
|
||
|
return decimal.Decimal{}, err
|
||
|
}
|
||
|
|
||
|
priceS := decimal.RequireFromString(priceNew)
|
||
|
|
||
|
var openPrice decimal.Decimal
|
||
|
difference := priceS.Mul(utils.Difference()) // 设置价差
|
||
|
switch tradeType {
|
||
|
case flags.TradeTypeBuy: // 买涨
|
||
|
openPrice = priceS.Sub(difference) // 开仓价格
|
||
|
case flags.TradeTypeSell: // 买跌
|
||
|
openPrice = priceS.Add(difference) // 开仓价格
|
||
|
default:
|
||
|
}
|
||
|
|
||
|
return openPrice, nil
|
||
|
}
|
||
|
|
||
|
// GetBotStockIdnTradeByOrderId
|
||
|
//
|
||
|
// @Description:
|
||
|
// @receiver uo
|
||
|
// @param ctx
|
||
|
// @param session
|
||
|
// @param orderId
|
||
|
// @return *models.BotStockIdnTrade
|
||
|
// @return error
|
||
|
func (uo *userOrderRepo) GetBotStockIdnTradeByOrderId(session *xorm.Session, orderId string) (*models.BotStockIdnTrade, error) {
|
||
|
var botStockIdnTrade []models.BotStockIdnTrade
|
||
|
if err := session.Table(flags.BotStockIdnTrade).
|
||
|
Where("order_id = ?", orderId).
|
||
|
Find(&botStockIdnTrade); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
for _, value := range botStockIdnTrade {
|
||
|
return &value, nil
|
||
|
}
|
||
|
|
||
|
return nil, nil
|
||
|
}
|
||
|
|
||
|
// GetBotUserStockIdnByUserIdAndStockId
|
||
|
//
|
||
|
// @Description:
|
||
|
// @receiver uo
|
||
|
// @param ctx
|
||
|
// @param session
|
||
|
// @param userId
|
||
|
// @param stockId
|
||
|
// @return *models.BotUserStockIdn
|
||
|
// @return error
|
||
|
func (uo *userOrderRepo) GetBotUserStockIdnByUserIdAndStockId(session *xorm.Session, userId int64, stockId string) (*models.BotUserStockIdn, error) {
|
||
|
var stockIDR []models.BotUserStockIdn
|
||
|
if err := session.Table(flags.BotUserStockIdn).
|
||
|
Where("user_id = ?", userId).
|
||
|
Where("stock_id = ?", stockId).
|
||
|
Find(&stockIDR); err != nil || len(stockIDR) <= 0 {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
for _, value := range stockIDR {
|
||
|
return &value, nil
|
||
|
}
|
||
|
|
||
|
return nil, nil
|
||
|
}
|
||
|
|
||
|
// UpdateBotStockIdnTradeByOrderId
|
||
|
//
|
||
|
// @Description:
|
||
|
// @receiver uo
|
||
|
// @param ctx
|
||
|
// @param session
|
||
|
// @param orderId
|
||
|
// @param stock
|
||
|
// @return error
|
||
|
func (uo *userOrderRepo) UpdateBotStockIdnTradeByOrderId(session *xorm.Session, orderId string, stock models.BotStockIdnTrade) error {
|
||
|
checkInt, err := session.Table(flags.BotStockIdnTrade).
|
||
|
Where("order_id = ?", orderId).
|
||
|
Update(&stock)
|
||
|
if err != nil || checkInt < 0 {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// CreateBotStockIdnTrade
|
||
|
//
|
||
|
// @Description:
|
||
|
// @receiver uo
|
||
|
// @param ctx
|
||
|
// @param session
|
||
|
// @param trade
|
||
|
// @return error
|
||
|
func (uo *userOrderRepo) CreateBotStockIdnTrade(session *xorm.Session, trade models.BotStockIdnTrade) error {
|
||
|
_, err := session.Table(flags.BotStockIdnTrade).Insert(&trade)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// CreateBotUserStockIdnFIRD
|
||
|
//
|
||
|
// @Description:
|
||
|
// @receiver uo
|
||
|
// @param ctx
|
||
|
// @param session
|
||
|
// @param stock
|
||
|
// @return error
|
||
|
func (uo *userOrderRepo) CreateBotUserStockIdnFIRD(session *xorm.Session, stock models.BotUserStockIdn) error {
|
||
|
_, err := session.Table(flags.BotUserStockIdn).Insert(&stock)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// UpdateBotUserStockIdnByUserIdAndStockId
|
||
|
//
|
||
|
// @Description:
|
||
|
// @receiver uo
|
||
|
// @param ctx
|
||
|
// @param session
|
||
|
// @param userId
|
||
|
// @param stockId
|
||
|
// @param stock
|
||
|
// @return error
|
||
|
func (uo *userOrderRepo) UpdateBotUserStockIdnByUserIdAndStockId(session *xorm.Session, userId int64, stockId string, stock models.BotUserStockIdn) error {
|
||
|
checkNum, err := session.Table(flags.BotUserStockIdn).
|
||
|
Where("user_id = ?", userId).
|
||
|
Where("stock_id = ?", stockId).
|
||
|
Update(&stock)
|
||
|
if err != nil || checkNum < 0 {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// StockIdnVoteDealType
|
||
|
//
|
||
|
// @Description:
|
||
|
// @receiver uo
|
||
|
// @param ctx
|
||
|
// @param order
|
||
|
// @return decimal.Decimal
|
||
|
// @return error
|
||
|
func (uo *userOrderRepo) StockIdnVoteDealType(order structure.ShareOrder) (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
|
||
|
}
|
||
|
|
||
|
// UpdateShareIdnVoteDealType
|
||
|
//
|
||
|
// @Description:
|
||
|
// @receiver uo
|
||
|
// @param ctx
|
||
|
// @param order
|
||
|
// @return decimal.Decimal
|
||
|
// @return error
|
||
|
func (uo *userOrderRepo) UpdateShareIdnVoteDealType(order *models.BotStockIdnTrade) (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
|
||
|
}
|
||
|
|
||
|
// VerifyBotStockIdnTradeOrderId
|
||
|
//
|
||
|
// @Description:
|
||
|
// @receiver uo
|
||
|
// @param ctx
|
||
|
// @param session
|
||
|
// @return string
|
||
|
// @return error
|
||
|
func (uo *userOrderRepo) VerifyBotStockIdnTradeOrderId(session *xorm.Session) (string, error) {
|
||
|
var orderId string
|
||
|
for {
|
||
|
// 生成订单ID
|
||
|
orderId = orders.CreateRandCodeOrder(10)
|
||
|
|
||
|
var orderList []models.BotStockIdnTrade
|
||
|
err := session.Table(flags.BotStockIdnTrade).Where("order_id = ?", orderId).Find(&orderList)
|
||
|
if err != nil || len(orderList) > 0 {
|
||
|
applogger.Error("%v VerifyBotStockIdnTradeOrderId.Find:%v", common.ErrShareIdn, err)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
break
|
||
|
}
|
||
|
|
||
|
return orderId, nil
|
||
|
}
|
||
|
|
||
|
// GetBotStockIdnTradeByOrderIdOrStatus
|
||
|
//
|
||
|
// @Description:
|
||
|
// @receiver uo
|
||
|
// @param ctx
|
||
|
// @param session
|
||
|
// @param orderId
|
||
|
// @param status
|
||
|
// @return *models.BotStockIdnTrade
|
||
|
// @return error
|
||
|
func (uo *userOrderRepo) GetBotStockIdnTradeByOrderIdOrStatus(session *xorm.Session, orderId string, status int) (*models.BotStockIdnTrade, error) {
|
||
|
var botStockIdnTrade []models.BotStockIdnTrade
|
||
|
if err := session.Table(flags.BotStockIdnTrade).
|
||
|
Where("order_id = ?", orderId).
|
||
|
Where("`status` = ?", status).
|
||
|
Find(&botStockIdnTrade); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
for _, value := range botStockIdnTrade {
|
||
|
return &value, nil
|
||
|
}
|
||
|
|
||
|
return nil, nil
|
||
|
}
|