vnpy使用
# vnpy社区
- https://www.vnpy.com/forum/
- 注册账号,colderleo,g7
- vnpy作者:陈晓优,QQ418225424
# 使用文档
https://www.vnpy.com/docs/cn/index.html
# 期权定价模型
隐含波动率 vnpy\app\option_master\pricing\black_76.py calculate_impv
# RQData
- RQData通过vnpy试用
(418225424):最近很多人问RQData试用申请的问题,找米筐那边沟通了下,现在通过vn.py专用的RQDATA页面申请试用,不需要上传名片:https://www.ricequant.com/welcome/purchase?utm_source=vnpy 另外RQData也已经推出国内期权的数据服务,vn.py这边也已经全部完成对接支持,实盘可以和之前期货一样完全无缝使用
- RQData替换为免费的天勤SDK
https://www.vnpy.com/forum/topic/2780-shi-yong-mian-fei-de-tian-qin-sdkshu-ju-ti-huan-fu-fei-de-rqdata
# https SSLError
https://www.cnblogs.com/hum0ro/p/9536033.html 只要安装一下几个requests依赖包就可以解决此问题。试了之后解决不了,应该是代理的原因。
pip install cryptography
pip install pyOpenSSL
pip install certifi
2
3
# 各个平台的交易品种代码
vt_symbol,合约.交易所,如:IF1905.CFFEX
连上交易所后,在‘帮助-合约查询’中可以查到交易所的所有合约(区分大小写)。常用的:
- XBTUSD.BITMEX
- BTC-USDT.OKEX
- btcusdt.HUOBI
- au2004.SHFE,黄金-上海期货
- IF2005.CFFEX,沪深300股指期货-中金
- BTCUSD.BYBIT
- BTCUSDT.BINANCE
# 源码
# cta_strategy 策略onticker
2.11每个策略只触发它自己对应的onticker。2.12版本加入了单策略多品种,还没看。
vnpy\app\cta_strategy\engine.py
def process_tick_event(self, event: Event):
""""""
tick = event.data
strategies = self.symbol_strategy_map[tick.vt_symbol]
if not strategies:
return
self.check_stop_order(tick)
for strategy in strategies:
if strategy.inited:
self.call_strategy_func(strategy, strategy.on_tick, tick)
2
3
4
5
6
7
8
9
10
11
12
13
# gateway的名字
# 通过下面的方式可以获取gateway的实例。
gateway_name = 'BINANCEF'
main_engine.get_gateway(gateway_name)
# 这里的gateway_name是在gateway初始化的时候定义的,例如 binancef_gateway.py中
class BinancefGateway(BaseGateway):
def __init__(self, event_engine: EventEngine):
super().__init__(event_engine, "BINANCEF")
2
3
4
5
6
7
8
# vt_symbol
# 通过vt_symbol获取gateway
contract:ContractData = main_engine.get_contract(vt_symbol)
if contract:
gateway = main_engine.get_gateway(contract.gateway_name)
2
3
4
5
# gateway: _ensure_connection
vnpy\api\websocket\websocket_client.py
def _ensure_connection(self):
""""""
triggered = False
with self._ws_lock:
if self._ws is None:
self._ws = self._create_connection(
self.host,
sslopt={"cert_reqs": ssl.CERT_NONE},
http_proxy_host=self.proxy_host,
http_proxy_port=self.proxy_port,
header=self.header
)
triggered = True
# 上面的self._create_connection()函数如果失败会抛出异常,如果没有抛出异常则表示成功连接
# 成功连接时执行下面的on_connected()
if triggered:
self.on_connected()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 使用日志
各个模块的日志如果要打印出来,需要将其log type注册到event_engine中。
log_engine:LogEngine = main_engine.get_engine('log')
self.recorder_engine.event_engine.register(EVENT_RECORDER_LOG, \
log_engine.process_log_event)
2
3
# bug 修改
# bybit加了一行类型转换
vnpy\gateway\bybit\bybit_gateway.py
class BybitRestApi(RestClient):
def on_query_contract(self, data: dict, request: Request):
# pricetick=d["price_filter"]["tick_size"],
pricetick=float(d["price_filter"]["tick_size"]),
2
3
4
# spread添加精度保留小数
有的交易所会提示精度要求太高。
vnpy\app\spread_trading\template.py
class SpreadAlgoTemplate:
def send_order(
leg = self.spread.legs[vt_symbol]
volume = round_to(volume, leg.min_volume)
# add float precious round. some exchanges don't accept too high precious
price = round(price, 6)
2
3
4
5
6
7
# data_recorder 写日志报错
def write_log(self, msg: str):
""""""
log = LogData(msg=msg, gateway_name=APP_NAME)
event = Event(type=EVENT_RECORDER_LOG, data=log)
self.event_engine.put(event)
# 原来的
# event = Event(
# EVENT_RECORDER_LOG,
# msg
# )
# self.event_engine.put(event)
2
3
4
5
6
7
8
9
10
11
12
# 功能修改
# websocket加上额外的expcet类型
vnpy\api\websocket\websocket_client.py
E:\gaoliu\mycode\vntest\vnpy\api\websocket\websocket_client.py
class WebsocketClient:
def _run(self):
try:
while self._active:
try:
self._ensure_connection()
...
# ws is closed before recv function is called
# For socket.error, see Issue #1608
except (
websocket.WebSocketConnectionClosedException,
websocket.WebSocketBadStatusException,
socket.error,
websocket.WebSocketAddressException, # 加上额外的expcet类型
):
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# settings
vnpy\app\data_recorder\engine.py
def load_setting(self):
# 原来的
setting = load_json(self.setting_filename)
self.tick_recordings = setting.get("tick", {})
self.bar_recordings = setting.get("bar", {})
# 修改
self.tick_recordings = {}
self.bar_recordings = {}
def save_setting(self):
# 修改为直接return
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 火币加上行情resubscribe
websocket重连时,重新订阅行情。后面用一个线程监控tick数据,如果3秒没有就resubscribe,这个不需要了。
class HuobiGateway(BaseGateway):
def __init__(self, event_engine):
self.subscribed: Dict[str, SubscribeRequest] = {}
def resubscribe(self):
for req in self.subscribed.values():
self.subscribe(req)
def subscribe(self, req: SubscribeRequest):
self.subscribed[req.symbol] = req
class HuobiTradeWebsocketApi(HuobiWebsocketApiBase):
def on_login(self):
self.gateway.write_log("交易Websocket API登录成功")
self.gateway.resubscribe()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 日志加上gateway
vnpy\trader\object.py
class LogData(BaseData):
def __post_init__(self):
self.time = datetime.now()
self.msg = f'{self.gateway_name} {self.msg}' # add
2
3
4
5
# 增加MainUi替换原来的MainWindow
- 增加文件vnpy\trader\ui\main_ui.py
- vnpy\trader\ui\widget.py 中增加 class GatewayWidget