通过脚本运行启动多个账户报错:zmq.error.ZMQError: Address in use
有大侠知道这个怎么解决吗?
xiaohe wrote:
可以获取拼好的连续主力、次主力合约的历史数据进行回测了
那次主力合约每个时间段都是不一样的,需要先每个时间段的次主力合约都先记录下来的吗
多谢,连续主力合约倒是可以获得,但是次主力合约也是一段时间改变一次的。
同品种主力合约和次主力合约,在交割后合约名称就发生变化,请问这个怎么做3年以上时间回测呢,因为每个时间段主力合约次主力合约都不同,有大侠知道的能帮个忙解析一下吗?
在CtpGateway里面 onRtnDepthMarketData 函数里面,每个价格会用函数 adjust_price 做一个调整 ,也就是去掉一些异常大的数值。但是这个在融航的接口rohon_gateway里面并没有做,但是我模拟账户发现融航也是会出现一些异常大的数值,所以这个函数在rohon_gateway也是需要的。请有看到的版主下次可以考虑优化一下。但是这个异常值怎么会产生,有知道大虾可以解析一下吗?
def onRtnDepthMarketData(self, data: dict):
"""
Callback of tick data update.
"""
symbol = data["InstrumentID"]
exchange = symbol_exchange_map.get(symbol, "")
if not exchange:
return
timestamp = f"{data['ActionDay']} {data['UpdateTime']}.{int(data['UpdateMillisec']/100)}"
dt = datetime.strptime(timestamp, "%Y%m%d %H:%M:%S.%f")
dt = CHINA_TZ.localize(dt)
tick = TickData(
symbol=symbol,
exchange=exchange,
datetime=dt,
name=symbol_name_map[symbol],
volume=data["Volume"],
open_interest=data["OpenInterest"],
last_price=adjust_price(data["LastPrice"]),
limit_up=data["UpperLimitPrice"],
limit_down=data["LowerLimitPrice"],
open_price=adjust_price(data["OpenPrice"]),
high_price=adjust_price(data["HighestPrice"]),
low_price=adjust_price(data["LowestPrice"]),
pre_close=adjust_price(data["PreClosePrice"]),
bid_price_1=adjust_price(data["BidPrice1"]),
ask_price_1=adjust_price(data["AskPrice1"]),
bid_volume_1=data["BidVolume1"],
ask_volume_1=data["AskVolume1"],
gateway_name=self.gateway_name
)
self.gateway.on_tick(tick)
这个算法实际运行过程中会出现BUG,有一些价位 会变得异常大。
def process_tick_event(self, event: Event):
tick_data = event.data
vt_symbol = tick_data.vt_symbol
# 过滤掉指数数据,由于下面会 publish EVENT_TICK,故此处需要过滤掉指数的 tick 数据
if vt_symbol == vt_symbol_to_index_symbol(vt_symbol):
return
sec_id = extract_sec_id(vt_symbol)
sec_id = sec_id.upper()
if sec_id not in self.subscribe_sec_id:
return
if tick_data.bid_price_1 > 9999999 or tick_data.ask_price_1 > 9999999:
return
# 下面合成最新的指数tick:每秒合成1个
symbol_tick_dict = self.symbol_tick_dict.setdefault(sec_id, {})
symbol_last_tick = self.symbol_last_tick.get(sec_id)
if symbol_last_tick and tick_data.datetime.second != symbol_last_tick.datetime.second and symbol_tick_dict:
index_tick = TickData(
symbol=f"{sec_id}8888",
exchange=tick_data.exchange,
datetime=tick_data.datetime,
gateway_name=tick_data.gateway_name,
name=self.subscribe_index_contract[sec_id].name
)
for tick in symbol_tick_dict.values():
index_tick.open_interest += tick.open_interest
if index_tick.open_interest:
for tick in symbol_tick_dict.values():
tick_weight = float(tick.open_interest) / index_tick.open_interest
index_tick.last_price += tick.last_price * tick_weight
index_tick.volume += tick.volume
index_tick.last_volume += tick.last_volume
index_tick.limit_up += tick.limit_up * tick_weight
index_tick.limit_down += tick.limit_down * tick_weight
index_tick.open_price += tick.open_price * tick_weight
index_tick.high_price += tick.high_price * tick_weight
index_tick.low_price += tick.low_price * tick_weight
index_tick.pre_close += tick.pre_close * tick_weight
index_tick.bid_price_1 += tick.bid_price_1 * tick_weight
index_tick.ask_price_1 += tick.ask_price_1 * tick_weight
index_tick.bid_volume_1 += tick.bid_volume_1
index_tick.ask_volume_1 += tick.ask_volume_1
# 5档有需要再加进来吧,省点计算资源
# tick_data.ask_price_2 += tick.ask_price_2 * tick_weight
# tick_data.ask_price_3 += tick.ask_price_3 * tick_weight
# tick_data.ask_price_4 += tick.ask_price_4 * tick_weight
# tick_data.ask_price_5 += tick.ask_price_5 * tick_weight
# tick_data.bid_price_2 += tick.bid_price_2 * tick_weight
# tick_data.bid_price_3 += tick.bid_price_3 * tick_weight
# tick_data.bid_price_4 += tick.bid_price_4 * tick_weight
# tick_data.bid_price_5 += tick.bid_price_5 * tick_weight
# tick_data.bid_volume_2 += tick.bid_volume_2 * tick_weight
# tick_data.bid_volume_3 += tick.bid_volume_3 * tick_weight
# tick_data.bid_volume_4 += tick.bid_volume_4 * tick_weight
# tick_data.bid_volume_5 += tick.bid_volume_5 * tick_weight
# tick_data.ask_volume_2 += tick.ask_volume_2 * tick_weight
# tick_data.ask_volume_3 += tick.ask_volume_3 * tick_weight
# tick_data.ask_volume_4 += tick.ask_volume_4 * tick_weight
# tick_data.ask_volume_5 += tick.ask_volume_5 * tick_weight
# 价格取整到最小价位变动
price_tick = self.subscribe_index_contract[sec_id].pricetick
index_tick.last_price = round_to(index_tick.last_price, price_tick)
index_tick.bid_price_1 = round_to(index_tick.bid_price_1, price_tick)
index_tick.ask_price_1 = round_to(index_tick.ask_price_1, price_tick)
index_tick.limit_up = round_to(index_tick.limit_up, price_tick)
index_tick.limit_down = round_to(index_tick.limit_down, price_tick)
index_tick.open_price = round_to(index_tick.open_price, price_tick)
index_tick.high_price = round_to(index_tick.high_price, price_tick)
index_tick.low_price = round_to(index_tick.low_price, price_tick)
index_tick.pre_close = round_to(index_tick.pre_close, price_tick)
self.on_event(EVENT_TICK, index_tick)
symbol_tick_dict[vt_symbol] = tick_data
self.symbol_last_tick[sec_id] = tick_data
合成代码:
def process_tick_event(self, event: Event):
tick_data = event.data
vt_symbol = tick_data.vt_symbol
# 过滤掉指数数据,由于下面会 publish EVENT_TICK,故此处需要过滤掉指数的 tick 数据
if vt_symbol == vt_symbol_to_index_symbol(vt_symbol):
return
sec_id = extract_sec_id(vt_symbol)
sec_id = sec_id.upper()
if sec_id not in self.subscribe_sec_id:
return
if tick_data.bid_price_1 > 9999999 or tick_data.ask_price_1 > 9999999:
return
# 下面合成最新的指数tick:每秒合成1个
symbol_tick_dict = self.symbol_tick_dict.setdefault(sec_id, {})
symbol_last_tick = self.symbol_last_tick.get(sec_id)
if symbol_last_tick and tick_data.datetime.second != symbol_last_tick.datetime.second and symbol_tick_dict:
index_tick = TickData(
symbol=f"{sec_id}8888",
exchange=tick_data.exchange,
datetime=tick_data.datetime,
gateway_name=tick_data.gateway_name,
name=self.subscribe_index_contract[sec_id].name
)
for tick in symbol_tick_dict.values():
index_tick.open_interest += tick.open_interest
if index_tick.open_interest:
for tick in symbol_tick_dict.values():
tick_weight = float(tick.open_interest) / index_tick.open_interest
index_tick.last_price += tick.last_price * tick_weight
index_tick.volume += tick.volume
index_tick.last_volume += tick.last_volume
index_tick.limit_up += tick.limit_up * tick_weight
index_tick.limit_down += tick.limit_down * tick_weight
index_tick.open_price += tick.open_price * tick_weight
index_tick.high_price += tick.high_price * tick_weight
index_tick.low_price += tick.low_price * tick_weight
index_tick.pre_close += tick.pre_close * tick_weight
index_tick.bid_price_1 += tick.bid_price_1 * tick_weight
index_tick.ask_price_1 += tick.ask_price_1 * tick_weight
index_tick.bid_volume_1 += tick.bid_volume_1
index_tick.ask_volume_1 += tick.ask_volume_1
# 5档有需要再加进来吧,省点计算资源
# tick_data.ask_price_2 += tick.ask_price_2 * tick_weight
# tick_data.ask_price_3 += tick.ask_price_3 * tick_weight
# tick_data.ask_price_4 += tick.ask_price_4 * tick_weight
# tick_data.ask_price_5 += tick.ask_price_5 * tick_weight
# tick_data.bid_price_2 += tick.bid_price_2 * tick_weight
# tick_data.bid_price_3 += tick.bid_price_3 * tick_weight
# tick_data.bid_price_4 += tick.bid_price_4 * tick_weight
# tick_data.bid_price_5 += tick.bid_price_5 * tick_weight
# tick_data.bid_volume_2 += tick.bid_volume_2 * tick_weight
# tick_data.bid_volume_3 += tick.bid_volume_3 * tick_weight
# tick_data.bid_volume_4 += tick.bid_volume_4 * tick_weight
# tick_data.bid_volume_5 += tick.bid_volume_5 * tick_weight
# tick_data.ask_volume_2 += tick.ask_volume_2 * tick_weight
# tick_data.ask_volume_3 += tick.ask_volume_3 * tick_weight
# tick_data.ask_volume_4 += tick.ask_volume_4 * tick_weight
# tick_data.ask_volume_5 += tick.ask_volume_5 * tick_weight
# 价格取整到最小价位变动
price_tick = self.subscribe_index_contract[sec_id].pricetick
if is_invalid_price(index_tick.last_price):
error_msg = f"INVALID PRICE: symbol={index_tick.vt_symbol}, index_tick={index_tick}, price_tick={price_tick}, tick_data={tick_data}"
#index_tick.last_price = get_max_price()
self.on_event(EVENT_INVALID_PARAM, error_msg)
if is_invalid_price(index_tick.bid_price_1):
error_msg = f"INVALID PRICE: symbol={index_tick.vt_symbol}, index_tick={index_tick}, price_tick={price_tick}, tick_data={tick_data}"
#index_tick.bid_price_1 = get_max_price()
self.on_event(EVENT_INVALID_PARAM, error_msg)
if is_invalid_price(index_tick.ask_price_1):
error_msg = f"INVALID PRICE: symbol={index_tick.vt_symbol}, index_tick={index_tick}, price_tick={price_tick}, tick_data={tick_data}"
#index_tick.ask_price_1 = get_max_price()
self.on_event(EVENT_INVALID_PARAM, error_msg)
if is_invalid_price(index_tick.limit_up):
error_msg = f"INVALID PRICE: symbol={index_tick.vt_symbol}, index_tick={index_tick}, price_tick={price_tick}, tick_data={tick_data}"
#index_tick.limit_up = get_max_price()
self.on_event(EVENT_INVALID_PARAM, error_msg)
if is_invalid_price(index_tick.limit_down):
error_msg = f"INVALID PRICE: symbol={index_tick.vt_symbol}, index_tick={index_tick}, price_tick={price_tick}, tick_data={tick_data}"
#index_tick.limit_down = get_max_price()
self.on_event(EVENT_INVALID_PARAM, error_msg)
if is_invalid_price(index_tick.open_price):
error_msg = f"INVALID PRICE: symbol={index_tick.vt_symbol}, index_tick={index_tick}, price_tick={price_tick}, tick_data={tick_data}"
#index_tick.open_price = get_max_price()
self.on_event(EVENT_INVALID_PARAM, error_msg)
if is_invalid_price(index_tick.high_price):
error_msg = f"INVALID PRICE: symbol={index_tick.vt_symbol}, index_tick={index_tick}, price_tick={price_tick}, tick_data={tick_data}"
#index_tick.high_price = get_max_price()
self.on_event(EVENT_INVALID_PARAM, error_msg)
if is_invalid_price(index_tick.low_price):
error_msg = f"INVALID PRICE: symbol={index_tick.vt_symbol}, index_tick={index_tick}, price_tick={price_tick}, tick_data={tick_data}"
#index_tick.low_price = get_max_price()
self.on_event(EVENT_INVALID_PARAM, error_msg)
if is_invalid_price(index_tick.pre_close):
error_msg = f"INVALID PRICE: symbol={index_tick.vt_symbol}, index_tick={index_tick}, price_tick={price_tick}, tick_data={tick_data}"
#index_tick.pre_close = get_max_price()
self.on_event(EVENT_INVALID_PARAM, error_msg)
index_tick.last_price = round_to(index_tick.last_price, price_tick)
index_tick.bid_price_1 = round_to(index_tick.bid_price_1, price_tick)
index_tick.ask_price_1 = round_to(index_tick.ask_price_1, price_tick)
index_tick.limit_up = round_to(index_tick.limit_up, price_tick)
index_tick.limit_down = round_to(index_tick.limit_down, price_tick)
index_tick.open_price = round_to(index_tick.open_price, price_tick)
index_tick.high_price = round_to(index_tick.high_price, price_tick)
index_tick.low_price = round_to(index_tick.low_price, price_tick)
index_tick.pre_close = round_to(index_tick.pre_close, price_tick)
event = Event(EVENT_TICK, index_tick)
self.event_engine.put(event)
symbol_tick_dict[vt_symbol] = tick_data
self.symbol_last_tick[sec_id] = tick_data
有没有人使用论坛里面提供的指数合成代码,发现一些异常的数据的?在合成tick数据的时候经常出现某个价格数值非常大的情况。像这 low_price=2.693714390689281e+305
2021-05-14 15:01:00,008 INFO: INVALID PRICE: symbol=Y8888.DCE, index_tick=TickData(gateway_name='ROHON', symbol='Y8888', exchange=<Exchange.DCE: 'DCE'>, datetime=datetime.datetime(2021, 5, 14, 15, 0, 58, 700000, tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>), name='Y指数合约', volume=1210563, open_interest=669368.0, last_price=8929.994789114508, last_volume=0, limit_up=9747.927561520717, limit_down=8472.98650069917, open_price=2.693714390689281e+305, high_price=2.693714390689281e+305, low_price=2.693714390689281e+305, pre_close=9157.514628724408, bid_price_1=8922.475926545636, bid_price_2=0, bid_price_3=0, bid_price_4=0, bid_price_5=0, ask_price_1=8934.2974268265, ask_price_2=0, ask_price_3=0, ask_price_4=0, ask_price_5=0, bid_volume_1=276, bid_volume_2=0, bid_volume_3=0, bid_volume_4=0, bid_volume_5=0, ask_volume_1=112, ask_volume_2=0, ask_volume_3=0, ask_volume_4=0, ask_volume_5=0), price_tick=2.0, tick_data=TickData(gateway_name='ROHON', symbol='y2105', exchange=<Exchange.DCE: 'DCE'>, datetime=datetime.datetime(2021, 5, 14, 15, 0, 58, 700000, tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>), name='豆油2105', volume=0, open_interest=1003.0, last_price=9676.0, last_volume=0, limit_up=10212.0, limit_down=8876.0, open_price=1.7976931348623157e+308, high_price=1.7976931348623157e+308, low_price=1.7976931348623157e+308, pre_close=9676.0, bid_price_1=9264.0, bid_price_2=0, bid_price_3=0, bid_price_4=0, bid_price_5=0, ask_price_1=9526.0, ask_price_2=0, ask_price_3=0, ask_price_4=0, ask_price_5=0, bid_volume_1=100, bid_volume_2=0, bid_volume_3=0, bid_volume_4=0, bid_volume_5=0, ask_volume_1=35, ask_volume_2=0, ask_volume_3=0, ask_volume_4=0, ask_volume_5=0)
2021-05-14 15:01:00,013 INFO: INVALID PRICE: symbol=Y8888.DCE, index_tick=TickData(gateway_name='ROHON', symbol='Y8888', exchange=<Exchange.DCE: 'DCE'>, datetime=datetime.datetime(2021, 5, 14, 15, 0, 58, 700000, tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>), name='Y指数合约', volume=1210563, open_interest=669368.0, last_price=8929.994789114508, last_volume=0, limit_up=9747.927561520717, limit_down=8472.98650069917, open_price=2.693714390689281e+305, high_price=2.693714390689281e+305, low_price=2.693714390689281e+305, pre_close=9157.514628724408, bid_price_1=8922.475926545636, bid_price_2=0, bid_price_3=0, bid_price_4=0, bid_price_5=0, ask_price_1=8934.2974268265, ask_price_2=0, ask_price_3=0, ask_price_4=0, ask_price_5=0, bid_volume_1=276, bid_volume_2=0, bid_volume_3=0, bid_volume_4=0, bid_volume_5=0, ask_volume_1=112, ask_volume_2=0, ask_volume_3=0, ask_volume_4=0, ask_volume_5=0), price_tick=2.0, tick_data=TickData(gateway_name='ROHON', symbol='y2105', exchange=<Exchange.DCE: 'DCE'>, datetime=datetime.datetime(2021, 5, 14, 15, 0, 58, 700000, tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>), name='豆油2105', volume=0, open_interest=1003.0, last_price=9676.0, last_volume=0, limit_up=10212.0, limit_down=8876.0, open_price=1.7976931348623157e+308, high_price=1.7976931348623157e+308, low_price=1.7976931348623157e+308, pre_close=9676.0, bid_price_1=9264.0, bid_price_2=0, bid_price_3=0, bid_price_4=0, bid_price_5=0, ask_price_1=9526.0, ask_price_2=0, ask_price_3=0, ask_price_4=0, ask_price_5=0, bid_volume_1=100, bid_volume_2=0, bid_volume_3=0, bid_volume_4=0, bid_volume_5=0, ask_volume_1=35, ask_volume_2=0, ask_volume_3=0, ask_volume_4=0, ask_volume_5=0)
2021-05-14 15:01:00,014 INFO: INVALID PRICE: symbol=Y8888.DCE, index_tick=TickData(gateway_name='ROHON', symbol='Y8888', exchange=<Exchange.DCE: 'DCE'>, datetime=datetime.datetime(2021, 5, 14, 15, 0, 58, 700000, tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>), name='Y指数合约', volume=1210563, open_interest=669368.0, last_price=8929.994789114508, last_volume=0, limit_up=9747.927561520717, limit_down=8472.98650069917, open_price=2.693714390689281e+305, high_price=2.693714390689281e+305, low_price=2.693714390689281e+305, pre_close=9157.514628724408, bid_price_1=8922.475926545636, bid_price_2=0, bid_price_3=0, bid_price_4=0, bid_price_5=0, ask_price_1=8934.2974268265, ask_price_2=0, ask_price_3=0, ask_price_4=0, ask_price_5=0, bid_volume_1=276, bid_volume_2=0, bid_volume_3=0, bid_volume_4=0, bid_volume_5=0, ask_volume_1=112, ask_volume_2=0, ask_volume_3=0, ask_volume_4=0, ask_volume_5=0), price_tick=2.0, tick_data=TickData(gateway_name='ROHON', symbol='y2105', exchange=<Exchange.DCE: 'DCE'>, datetime=datetime.datetime(2021, 5, 14, 15, 0, 58, 700000, tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>), name='豆油2105', volume=0, open_interest=1003.0, last_price=9676.0, last_volume=0, limit_up=10212.0, limit_down=8876.0, open_price=1.7976931348623157e+308, high_price=1.7976931348623157e+308, low_price=1.7976931348623157e+308, pre_close=9676.0, bid_price_1=9264.0, bid_price_2=0, bid_price_3=0, bid_price_4=0, bid_price_5=0, ask_price_1=9526.0, ask_price_2=0, ask_price_3=0, ask_price_4=0, ask_price_5=0, bid_volume_1=100, bid_volume_2=0, bid_volume_3=0, bid_volume_4=0, bid_volume_5=0, ask_volume_1=35, ask_volume_2=0, ask_volume_3=0, ask_volume_4=0, ask_volume_5=0)
2021-05-14 15:01:00,015 INFO: self.last_tick_times[Y8888.DCE]:2021-05-14 15:00:00+08:00, tick.datetime.minute:0, tick=TickData(gateway_name='ROHON', symbol='Y8888', exchange=<Exchange.DCE: 'DCE'>, datetime=datetime.datetime(2021, 5, 14, 15, 0, 58, 700000, tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>), name='Y指数合约', volume=1210563, open_interest=669368.0, last_price=8930.0, last_volume=0, limit_up=9748.0, limit_down=8472.0, open_price=2.693714390689281e+305, high_price=2.693714390689281e+305, low_price=2.693714390689281e+305, pre_close=9158.0, bid_price_1=8922.0, bid_price_2=0, bid_price_3=0, bid_price_4=0, bid_price_5=0, ask_price_1=8934.0, ask_price_2=0, ask_price_3=0, ask_price_4=0, ask_price_5=0, bid_volume_1=276, bid_volume_2=0, bid_volume_3=0, bid_volume_4=0, bid_volume_5=0, ask_volume_1=112, ask_volume_2=0, ask_volume_3=0, ask_volume_4=0, ask_volume_5=0)
由于需要对接MOM交易接口(不是融航),需要把对方给的CTP头文件和交易库转成python库即 vnctpmd 和 vnctptd,有没有大佬指导下怎么编译效果高一点?或者分享一下整个编译的流程。最好是windows环境下。
已可以,多谢大虾。
还有就是通过vnstation 只选择融航接口是能够连接上。但是用run.py就会报4097错误,这个是什么原因呢?
哦,不过我已经连接上融航和杰宜斯了。多谢!
现在版本不是6.3.19吗?我看到融航里面说现在已经支持了6.3.19,而且我用最新的代码现在是可以直接连上融航了。
由于需要,接入杰宜斯平台所需要对应ctp版本为 6.3.15,有哪位大侠知道vn哪个版本是基于ctp 6.3.15版本的吗?貌似还没有看到有接入杰宜斯系统的。
多谢,下载vcredist库后,在vnstation只加载融航接口是可以连接的上。但是还有一个问题,就是用脚本run.py只加载融航接口还是报4097错误。请问这个有解决方案不?
我就是安装你的连接下载最新的版本,采用融航的模拟账户去登录,就一直报4097错误。这个问题有没有一个统一明确的解决方案呢?因为我看最新版本是支持融航的,而且API也是6.3.19,库也是和融航要求的一样。但是新接触还是很容易就报错。
使用模拟账户测试的,ctptest_gateway 和 rohon_gateway 都是报一样的错误来的。