[增强] 恢复账号资金属性,增加风控(仓位百分比)
This commit is contained in:
parent
4f071444f5
commit
df102d5237
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,13 @@
|
||||
""""""
|
||||
|
||||
from copy import copy
|
||||
from collections import defaultdict
|
||||
from datetime import datetime
|
||||
from vnpy.trader.constant import Offset
|
||||
from vnpy.trader.object import OrderRequest, LogData
|
||||
from vnpy.event import Event, EventEngine, EVENT_TIMER
|
||||
from vnpy.trader.engine import BaseEngine, MainEngine
|
||||
from vnpy.trader.event import EVENT_TRADE, EVENT_ORDER, EVENT_LOG
|
||||
from vnpy.trader.event import EVENT_TRADE, EVENT_ORDER, EVENT_LOG, EVENT_ACCOUNT
|
||||
from vnpy.trader.constant import Status
|
||||
from vnpy.trader.utility import load_json, save_json
|
||||
|
||||
@ -23,20 +26,28 @@ class RiskManagerEngine(BaseEngine):
|
||||
self.active = False
|
||||
|
||||
self.order_flow_count = 0
|
||||
self.order_flow_limit = 50
|
||||
self.order_flow_limit = 500
|
||||
|
||||
self.order_flow_clear = 1
|
||||
self.order_flow_timer = 0
|
||||
|
||||
self.order_size_limit = 100
|
||||
self.order_size_limit = 1000
|
||||
|
||||
self.trade_count = 0
|
||||
self.trade_limit = 1000
|
||||
self.trade_limit = 10000
|
||||
|
||||
self.order_cancel_limit = 500
|
||||
self.order_cancel_limit = 5000
|
||||
self.order_cancel_counts = defaultdict(int)
|
||||
|
||||
self.active_order_limit = 50
|
||||
self.active_order_limit = 500
|
||||
|
||||
# 总仓位相关(0~100+)
|
||||
self.percent_limit = 100 # 仓位比例限制
|
||||
self.last_over_time = None # 启动风控后,最后一次超过仓位限制的时间
|
||||
|
||||
self.account_dict = {} # 资金账号信息
|
||||
self.gateway_dict = {} # 记录gateway对应的仓位比例
|
||||
self.currency_list = [] # 资金账号风控管理得币种
|
||||
|
||||
self.load_setting()
|
||||
self.register_event()
|
||||
@ -66,7 +77,7 @@ class RiskManagerEngine(BaseEngine):
|
||||
self.trade_limit = setting["trade_limit"]
|
||||
self.active_order_limit = setting["active_order_limit"]
|
||||
self.order_cancel_limit = setting["order_cancel_limit"]
|
||||
|
||||
self.percent_limit = setting.get('percent_limit', 100)
|
||||
if self.active:
|
||||
self.write_log("交易风控功能启动")
|
||||
else:
|
||||
@ -82,6 +93,7 @@ class RiskManagerEngine(BaseEngine):
|
||||
"trade_limit": self.trade_limit,
|
||||
"active_order_limit": self.active_order_limit,
|
||||
"order_cancel_limit": self.order_cancel_limit,
|
||||
"percent_limit": self.percent_limit
|
||||
}
|
||||
return setting
|
||||
|
||||
@ -103,6 +115,7 @@ class RiskManagerEngine(BaseEngine):
|
||||
self.event_engine.register(EVENT_TRADE, self.process_trade_event)
|
||||
self.event_engine.register(EVENT_TIMER, self.process_timer_event)
|
||||
self.event_engine.register(EVENT_ORDER, self.process_order_event)
|
||||
self.event_engine.register(EVENT_ACCOUNT, self.process_account_event)
|
||||
|
||||
def process_order_event(self, event: Event):
|
||||
""""""
|
||||
@ -124,6 +137,47 @@ class RiskManagerEngine(BaseEngine):
|
||||
self.order_flow_count = 0
|
||||
self.order_flow_timer = 0
|
||||
|
||||
def process_account_event(self, event):
|
||||
"""更新账号资金
|
||||
add by Incense
|
||||
"""
|
||||
account = event.data
|
||||
|
||||
# 如果有币种过滤,就进行过滤动作
|
||||
if len(self.currency_list) > 0:
|
||||
if account.currency not in self.currency_list:
|
||||
return
|
||||
|
||||
# 净值为0得不做处理
|
||||
if account.balance == 0:
|
||||
return
|
||||
|
||||
# 保存在dict中
|
||||
k = u'{}_{}'.format(account.vt_accountid, account.currency)
|
||||
self.account_dict.update({k: copy(account)})
|
||||
|
||||
# 计算当前资金仓位
|
||||
if account.balance == 0:
|
||||
account_percent = 0
|
||||
else:
|
||||
account_percent = round((account.balance - account.available) * 100 / account.balance, 2)
|
||||
|
||||
if not self.active:
|
||||
return
|
||||
|
||||
# 更新gateway对应的当前资金仓位
|
||||
self.gateway_dict.update({account.gateway_name: account_percent})
|
||||
|
||||
# 判断资金仓位超出
|
||||
if account_percent > self.percent_limit:
|
||||
if self.last_over_time is None or (
|
||||
datetime.now() - self.last_over_time).total_seconds() > 60 * 10:
|
||||
self.last_over_time = datetime.now()
|
||||
msg = u'账号:{} 今净值:{},保证金占用{} 超过设定:{}' \
|
||||
.format(account.vt_accountid,
|
||||
account.balance, account_percent, self.percent_limit)
|
||||
self.write_log(msg)
|
||||
|
||||
def write_log(self, msg: str):
|
||||
""""""
|
||||
log = LogData(msg=msg, gateway_name="RiskManager")
|
||||
@ -170,6 +224,11 @@ class RiskManagerEngine(BaseEngine):
|
||||
f"当日{req.symbol}撤单次数{self.order_cancel_counts[req.symbol]},超过限制{self.order_cancel_limit}")
|
||||
return False
|
||||
|
||||
# 开仓时,检查是否超过保证金比率
|
||||
if req.offset == Offset.OPEN and self.gateway_dict.get(gateway_name, 0) > self.percent_limit:
|
||||
self.write_log(f'当前资金仓位{self.gateway_dict[gateway_name]}超过仓位限制:{self.percent_limit}')
|
||||
return False
|
||||
|
||||
# Add flow count if pass all checks
|
||||
self.order_flow_count += 1
|
||||
return True
|
||||
|
@ -31,6 +31,7 @@ class RiskManager(QtWidgets.QDialog):
|
||||
self.trade_limit_spin = RiskManagerSpinBox()
|
||||
self.active_limit_spin = RiskManagerSpinBox()
|
||||
self.cancel_limit_spin = RiskManagerSpinBox()
|
||||
self.percent_limit_spin = RiskManagerSpinBox()
|
||||
|
||||
save_button = QtWidgets.QPushButton("保存")
|
||||
save_button.clicked.connect(self.save_setting)
|
||||
@ -44,6 +45,7 @@ class RiskManager(QtWidgets.QDialog):
|
||||
form.addRow("总成交上限(笔)", self.trade_limit_spin)
|
||||
form.addRow("活动委托上限(笔)", self.active_limit_spin)
|
||||
form.addRow("合约撤单上限(笔)", self.cancel_limit_spin)
|
||||
form.addRow("资金仓位上限(%)", self.percent_limit_spin)
|
||||
form.addRow(save_button)
|
||||
|
||||
self.setLayout(form)
|
||||
@ -68,6 +70,7 @@ class RiskManager(QtWidgets.QDialog):
|
||||
"trade_limit": self.trade_limit_spin.value(),
|
||||
"active_order_limit": self.active_limit_spin.value(),
|
||||
"order_cancel_limit": self.cancel_limit_spin.value(),
|
||||
"percent_limit": self.percent_limit_spin.value(),
|
||||
}
|
||||
|
||||
self.rm_engine.update_setting(setting)
|
||||
@ -89,6 +92,7 @@ class RiskManager(QtWidgets.QDialog):
|
||||
self.trade_limit_spin.setValue(setting["trade_limit"])
|
||||
self.active_limit_spin.setValue(setting["active_order_limit"])
|
||||
self.cancel_limit_spin.setValue(setting["order_cancel_limit"])
|
||||
self.percent_limit_spin.setValue(setting.get('percent_limit', 100))
|
||||
|
||||
def exec_(self):
|
||||
""""""
|
||||
|
@ -13,7 +13,7 @@
|
||||
"mi_symbol": "ag2007",
|
||||
"full_symbol": "AG2007",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.07,
|
||||
"margin_rate": 0.08,
|
||||
"symbol_size": 15,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -22,7 +22,7 @@
|
||||
"mi_symbol": "al2003",
|
||||
"full_symbol": "AL2003",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.07,
|
||||
"margin_rate": 0.1,
|
||||
"symbol_size": 5,
|
||||
"price_tick": 5.0
|
||||
},
|
||||
@ -31,7 +31,7 @@
|
||||
"mi_symbol": "AP005",
|
||||
"full_symbol": "AP2005",
|
||||
"exchange": "CZCE",
|
||||
"margin_rate": 0.08,
|
||||
"margin_rate": 0.07,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -40,7 +40,7 @@
|
||||
"mi_symbol": "au2006",
|
||||
"full_symbol": "AU2006",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.06,
|
||||
"margin_rate": 0.08,
|
||||
"symbol_size": 1000,
|
||||
"price_tick": 0.02
|
||||
},
|
||||
@ -67,7 +67,7 @@
|
||||
"mi_symbol": "bu2006",
|
||||
"full_symbol": "BU2006",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.09,
|
||||
"margin_rate": 0.1,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 2.0
|
||||
},
|
||||
@ -112,7 +112,7 @@
|
||||
"mi_symbol": "cu2003",
|
||||
"full_symbol": "CU2003",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.07,
|
||||
"margin_rate": 0.09,
|
||||
"symbol_size": 5,
|
||||
"price_tick": 10.0
|
||||
},
|
||||
@ -139,7 +139,7 @@
|
||||
"mi_symbol": "eg2005",
|
||||
"full_symbol": "EG2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.06,
|
||||
"margin_rate": 0.05,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -148,9 +148,9 @@
|
||||
"mi_symbol": "fb2005",
|
||||
"full_symbol": "FB2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.1,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 0.5
|
||||
"margin_rate": 0.2,
|
||||
"symbol_size": 500,
|
||||
"price_tick": 0.05
|
||||
},
|
||||
"FG": {
|
||||
"underlying_symbol": "FG",
|
||||
@ -166,7 +166,7 @@
|
||||
"mi_symbol": "fu2005",
|
||||
"full_symbol": "FU2005",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.1,
|
||||
"margin_rate": 0.2,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -175,7 +175,7 @@
|
||||
"mi_symbol": "hc2005",
|
||||
"full_symbol": "HC2005",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.08,
|
||||
"margin_rate": 0.1,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -184,7 +184,7 @@
|
||||
"mi_symbol": "i2005",
|
||||
"full_symbol": "I2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.08,
|
||||
"margin_rate": 0.05,
|
||||
"symbol_size": 100,
|
||||
"price_tick": 0.5
|
||||
},
|
||||
@ -193,7 +193,7 @@
|
||||
"mi_symbol": "IC2003",
|
||||
"full_symbol": "IC2003",
|
||||
"exchange": "CFFEX",
|
||||
"margin_rate": 0.12,
|
||||
"margin_rate": 0.1,
|
||||
"symbol_size": 200,
|
||||
"price_tick": 0.2
|
||||
},
|
||||
@ -220,7 +220,7 @@
|
||||
"mi_symbol": "j2005",
|
||||
"full_symbol": "J2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.08,
|
||||
"margin_rate": 0.05,
|
||||
"symbol_size": 100,
|
||||
"price_tick": 0.5
|
||||
},
|
||||
@ -229,7 +229,7 @@
|
||||
"mi_symbol": "jd2005",
|
||||
"full_symbol": "JD2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.07,
|
||||
"margin_rate": 0.08,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -238,7 +238,7 @@
|
||||
"mi_symbol": "jm2005",
|
||||
"full_symbol": "JM2005",
|
||||
"exchange": "DCE",
|
||||
"margin_rate": 0.08,
|
||||
"margin_rate": 0.05,
|
||||
"symbol_size": 60,
|
||||
"price_tick": 0.5
|
||||
},
|
||||
@ -328,7 +328,7 @@
|
||||
"mi_symbol": "pb2003",
|
||||
"full_symbol": "PB2003",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.07,
|
||||
"margin_rate": 0.1,
|
||||
"symbol_size": 5,
|
||||
"price_tick": 5.0
|
||||
},
|
||||
@ -355,7 +355,7 @@
|
||||
"mi_symbol": "rb2005",
|
||||
"full_symbol": "RB2005",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.08,
|
||||
"margin_rate": 0.1,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -373,7 +373,7 @@
|
||||
"mi_symbol": "RM005",
|
||||
"full_symbol": "RM2005",
|
||||
"exchange": "CZCE",
|
||||
"margin_rate": 0.06,
|
||||
"margin_rate": 0.05,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -391,7 +391,7 @@
|
||||
"mi_symbol": "RS011",
|
||||
"full_symbol": "RS2011",
|
||||
"exchange": "CZCE",
|
||||
"margin_rate": 0.2,
|
||||
"margin_rate": 0.05,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -400,7 +400,7 @@
|
||||
"mi_symbol": "ru2005",
|
||||
"full_symbol": "RU2005",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.09,
|
||||
"margin_rate": 0.1,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 5.0
|
||||
},
|
||||
@ -418,7 +418,7 @@
|
||||
"mi_symbol": "sc2003",
|
||||
"full_symbol": "SC2003",
|
||||
"exchange": "INE",
|
||||
"margin_rate": 0.07,
|
||||
"margin_rate": 0.05,
|
||||
"symbol_size": 1000,
|
||||
"price_tick": 0.1
|
||||
},
|
||||
@ -427,7 +427,7 @@
|
||||
"mi_symbol": "SF005",
|
||||
"full_symbol": "SF2005",
|
||||
"exchange": "CZCE",
|
||||
"margin_rate": 0.07,
|
||||
"margin_rate": 0.05,
|
||||
"symbol_size": 5,
|
||||
"price_tick": 2.0
|
||||
},
|
||||
@ -436,7 +436,7 @@
|
||||
"mi_symbol": "SM005",
|
||||
"full_symbol": "SM2005",
|
||||
"exchange": "CZCE",
|
||||
"margin_rate": 0.07,
|
||||
"margin_rate": 0.05,
|
||||
"symbol_size": 5,
|
||||
"price_tick": 2.0
|
||||
},
|
||||
@ -445,7 +445,7 @@
|
||||
"mi_symbol": "sn2006",
|
||||
"full_symbol": "SN2006",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.08,
|
||||
"margin_rate": 0.09,
|
||||
"symbol_size": 1,
|
||||
"price_tick": 10.0
|
||||
},
|
||||
@ -490,7 +490,7 @@
|
||||
"mi_symbol": "TA005",
|
||||
"full_symbol": "TA2005",
|
||||
"exchange": "CZCE",
|
||||
"margin_rate": 0.06,
|
||||
"margin_rate": 0.05,
|
||||
"symbol_size": 5,
|
||||
"price_tick": 2.0
|
||||
},
|
||||
@ -535,7 +535,7 @@
|
||||
"mi_symbol": "WH011",
|
||||
"full_symbol": "WH2011",
|
||||
"exchange": "CZCE",
|
||||
"margin_rate": 0.07,
|
||||
"margin_rate": 0.05,
|
||||
"symbol_size": 20,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -544,7 +544,7 @@
|
||||
"mi_symbol": "wr2012",
|
||||
"full_symbol": "WR2012",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.08,
|
||||
"margin_rate": 0.2,
|
||||
"symbol_size": 10,
|
||||
"price_tick": 1.0
|
||||
},
|
||||
@ -562,7 +562,7 @@
|
||||
"mi_symbol": "ZC005",
|
||||
"full_symbol": "ZC2005",
|
||||
"exchange": "CZCE",
|
||||
"margin_rate": 0.06,
|
||||
"margin_rate": 0.05,
|
||||
"symbol_size": 100,
|
||||
"price_tick": 0.2
|
||||
},
|
||||
@ -571,7 +571,7 @@
|
||||
"mi_symbol": "zn2003",
|
||||
"full_symbol": "ZN2003",
|
||||
"exchange": "SHFE",
|
||||
"margin_rate": 0.07,
|
||||
"margin_rate": 0.1,
|
||||
"symbol_size": 5,
|
||||
"price_tick": 5.0
|
||||
}
|
||||
|
@ -772,11 +772,19 @@ class CtpTdApi(TdApi):
|
||||
|
||||
account = AccountData(
|
||||
accountid=data["AccountID"],
|
||||
pre_balance=data['PreBalance'],
|
||||
balance=data["Balance"],
|
||||
frozen=data["FrozenMargin"] + data["FrozenCash"] + data["FrozenCommission"],
|
||||
gateway_name=self.gateway_name
|
||||
)
|
||||
account.available = data["Available"]
|
||||
account.commission = data['Commission']
|
||||
account.margin = data['CurrMargin']
|
||||
account.close_profit = data['CloseProfit']
|
||||
account.holding_profit = data['PositionProfit']
|
||||
account.trading_day = str(data['TradingDay'])
|
||||
if '-' not in account.trading_day and len(account.trading_day)== 8:
|
||||
account.trading_day = account.trading_day[0:4] + '-' + account.trading_day[4:6] + '-' + account.trading_day[6:8]
|
||||
|
||||
self.gateway.on_account(account)
|
||||
|
||||
|
@ -220,9 +220,15 @@ class AccountData(BaseData):
|
||||
"""
|
||||
|
||||
accountid: str
|
||||
|
||||
balance: float = 0
|
||||
frozen: float = 0
|
||||
pre_balance: float = 0 # 昨净值
|
||||
balance: float = 0 # 当前净值
|
||||
frozen: float = 0 # 冻结资金
|
||||
currency: str = "" # 币种
|
||||
commission: float = 0 # 手续费
|
||||
margin: float = 0 # 使用保证金
|
||||
close_profit: float = 0 # 平仓盈亏
|
||||
holding_profit: float = 0 # 持仓盈亏
|
||||
trading_day: str = "" # 当前交易日
|
||||
|
||||
def __post_init__(self):
|
||||
""""""
|
||||
|
@ -480,9 +480,14 @@ class AccountMonitor(BaseMonitor):
|
||||
|
||||
headers = {
|
||||
"accountid": {"display": "账号", "cell": BaseCell, "update": False},
|
||||
"balance": {"display": "余额", "cell": BaseCell, "update": True},
|
||||
"pre_balance": {"display": "昨净值", "cell": BaseCell, "update": False},
|
||||
"balance": {"display": "净值", "cell": BaseCell, "update": True},
|
||||
"frozen": {"display": "冻结", "cell": BaseCell, "update": True},
|
||||
"margin": {"display": "保证金", "cell": BaseCell, "update": True},
|
||||
"available": {"display": "可用", "cell": BaseCell, "update": True},
|
||||
"commission": {"display": "手续费", "cell": BaseCell, "update": True},
|
||||
"close_profit": {"display": "平仓收益", "cell": BaseCell, "update": True},
|
||||
"holding_profit": {"display": "持仓收益", "cell": BaseCell, "update": True},
|
||||
"gateway_name": {"display": "接口", "cell": BaseCell, "update": False},
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user