1.Lib\site-packages\vnpy路径下新建user_tools文件夹,放入pricetick.py
pricetick.py内容如下:
import json
import os
class PRICETICK(object):
PATH = os.environ["USERPROFILE"] + "\\.vntrader\\unit.json"
PRICE_TICK = 0.0 #最小跳动点 float
UNIT = 0 #合约乘数 int
def get_unit(self,symbol):
with open(self.PATH,"r",encoding="utf_8") as f:
result = json.load(f)
for key_symbol in result:
if key_symbol == symbol:
self.PRICE_TICK = float(result[symbol][0]) #json读取最小跳动点
self.UNIT = int(result[symbol][1]) #json读取合约乘数
break
return self.PRICE_TICK,self.UNIT
2. .vntrader\unit.json 在.\vntrader文件夹下,新建unit.json, json文件存储所有标的最小跳动点,合约乘数
unit.json内容如下:
{
"IF":["0.2","300"],
"IC":["0.2","200"],
"IH":["0.2","300"],
"IM":["0.2","200"],
"T":["0.005","10000"],
"TF":["0.005","10000"],
"TS":["0.005","20000"],
"TL":["0.01","10000"],
"AU":["0.02","1000"],
"AG":["1","15"],
"CU":["10","5"],
"AL":["5","5"],
"ZN":["5","5"],
"PB":["5","5"],
"NI":["10","1"],
"SN":["10","1"],
"RB":["1","10"],
"WR":["1","10"],
"I":["0.5","100"],
"HC":["1","10"],
"SS":["5","5"],
"SF":["2","5"],
"SM":["2","5"],
"JM":["0.5","60"],
"J":["0.5","100"],
"ZC":["0.2","100"],
"FG":["1","20"],
"SP":["2","10"],
"FU":["1","10"],
"LU":["1","10"],
"SC":["0.1","1000"],
"BC":["10","5"],
"EC":["0.1","50"],
"BU":["1","10"],
"PG":["1","20"],
"RU":["5","10"],
"NR":["5","10"],
"L":["1","5"],
"TA":["2","5"],
"V":["1","5"],
"EG":["1","10"],
"MA":["1","10"],
"PP":["1","5"],
"EB":["1","5"],
"UR":["1","20"],
"SA":["1","20"],
"C":["1","10"],
"A":["1","10"],
"CS":["1","10"],
"B":["1","10"],
"M":["1","10"],
"Y":["2","10"],
"RM":["1","10"],
"OI":["1","10"],
"P":["2","10"],
"CF":["5","5"],
"SR":["1","10"],
"JD":["1","10"],
"AP":["1","10"],
"CJ":["5","5"],
"PF":["2","5"],
"PK":["2","5"],
"AO":["1","20"],
"LC":["50","1"],
"SI":["5","5"],
"BR":["5","5"],
"RR":["1","10"],
"LH":["5","16"],
"PX":["2","5"],
"SH":["1","30"]
}
3.在自己的策略中调用
from vnpy.user_tools.pricetick import PRICETICK
初始化时候def __init__():
实例化 self.contract = PRICETICK()
获取标的 self.symbol = "".join(re.findall(r"\D+",self.get_data()["vt_symbol"].split(".")[0])).upper()
提取最小变动价格,合约乘数 self.PRICE_TICK,self.UNIT = self.contract.get_unit(self.symbol) #从json提取最小变动价位,合约乘数
CtaTemplate中,cta_engine.get_size()这个合约乘数获取,是从接入的数据源获得的嘛?比如接入rqdata,这个get_size()数据就是rqdata的数据
dataframe 数据,如上图,需要数据入库SqliteDatabase,先已经将dataframe数据整理成BarData
入库如下:
_from vnpy.trader.database import BaseDatabase, get_database
database: BaseDatabase = get_database()
database.save_bardata(bars)
遇到这个时间戳转换问题,如何解决呢?
在on_trade函数下,判断self.pos>0,且没有挂止损单,发出止损self.sell(stop_price,abs(self.pos),stop=True),最后发现发出去的止损单和仓位不一致;观察了下,可能是一个仓位分了多次成交,on_trade只收到第一单成交的仓位,这个如何解决?
vnpy自带的python3.10.2 版本,对以前自己写的程序不兼容,怎么简单更换vnpy自带的版本不影响vnstation现有的程序?
分时图均价线,如何计算VWAP?直接在on_tick回调函数里面,用amount += tick.last_price * tick.last_volume,然后vwap = amount / tick.volume?
在腾讯云2核4G window server2012上,安装veighna3.0版本,点击黑马图标无反应,命令veighna 启动,显示DLL Load failed while importing QtwebEngineWidgets后,自己pip 安装了pyqt5,和pyqt6 都不行,有pip安装了QtwebEngine,任然是相同的报错;
2022-05-05 19:35:54 E:\vnstuido\lib\site-packages\vnpy\trader\setting.py:32: PytzUsageWarning: The zone attribute is specific to pytz's interface; please migrate to a new time zone provider. For more details on how to do so, see https://pytz-deprecation-shim.readthedocs.io/en/latest/migration.html
"database.timezone": getlocalzone().zone,
2022-05-05 19:35:55 找不到数据服务驱动vnpy,使用默认的RQData数据服务
看了下Market Radar 后续 进一步加入图表显示(参考文华的组合)、条件提醒(警报和发微信)、策略信号订阅等功能,很期待这些功能
单子入场,例如多头入场,立即发出limit 止盈单,和stop止损单,这时候limit 单直接发送到交易所服务器,但stop止损单在本地挂着;如果价格先去止损单方向,因为limit止盈单已经发到服务器,止损单触发也会因为可用仓位不足,而不能止损;如果价格先去止盈单,则不会出现上述状况;
1.那么如何处理第一种情况,因为limit单占用坑位导致仓位不足无法止损?加个bar.high_price >= long_tp判断在发单似乎可以;
2.如果获取真实入场价格trade.price,long_sl = trade.price - X,仓位大于0时候发出止损单,今天却遇到因为trade_price 还没有返回即为0时,直接发出了stop止损单,报价为—X,直接止损了;这种情况如何处理?
今天登陆Vnstation,点击更新,部分没有更新成功,显示pip需要更新到最新版本;退出后用pip install --upgrade pip 升级失败,然后点击vnstation完全没有反应了,但可以通过run.py登陆vnTrader;在cmd命令下,pip找不到了,检查环境变量没问题,直接切换到vnstudio——scripts目录powershell也找不到pip模块(pip.exe在改目录下能看到);尝试卸载不行,直接在上述scripts目录下运行esay_install.exe安装也没成功。需要如何处理?
算法里面看到grid_algo网格算法,有没有向ctastrategy一样,写个gridstrategy模板,研究在vnpy上实现etf,价差,或者其它标的的网格策略实盘以及回测,自己写了下网格策略,成交总会出问题,有个模板学习就方便了
1.有没什么方法可以同时启动多个vntrader?
以前挂stop单成交,都是第一根k线走完才能发出单子,要实现开盘第一k符合条件就立即入场,止损后依然可以在on_bar中挂stop单入场,研究了下细粒度挂撤单操作,思路是在on_bar中产生信号,接着在on_tick中限价委托成交;
on_bar中:
if self.pos == 0:
if bar.datetime.minute == self.start_time.minute:
if bar.high_price >= self.buy_break:
self.target_pos = self.fixed_size
elif not self.long_vt_orderids :(疑问:on_tick中限价买单,要求只成交一次,且没有记录orderid,不清楚on_tick里的buy会不会影响到这个long_vt_orderids,实盘中第1k入场,止损后,就不在发出单子了,需要如何解决?)
self.long_vt_orderids = self.buy(stop=true)
self.vt_orderids.extend(self.long_vt_orderids)
on_tick中:
volume = self.target_pos -self.pos
if volume > 0:
if not self.long_entered:
self.buy(stop=False)
1.vnpy.app新建user_tools文件夹trading_hour.py放入user_tools
trading_hour.py如下:
from datetime import datetime,time,timedelta
import json
class TRADINGHOUR(object):
PATH = "***.vntrader/trading_hour.json" #PATH填trading_hour.json在电脑的绝对路径,trading_hour.json放入在vntrader目录下,如:c:/users/电脑名/vntrader/trading_hour.json
time_switch = 0
start_time = ""
end_time = ""
def get_trading_time(self,symbol): #读取存入json中的标的开收盘时间
with open(self.PATH,"r",encoding="utf_8") as f:
trading_hour = json.load(f)
for key_symbol in trading_hour:
if key_symbol == symbol:
start = trading_hour[symbol][0]
end = trading_hour[symbol][1]
break
self.start_time = datetime.strptime(start,"%H:%M:%S") #datetime对象,后面比较时候要转换成time对象
self.end_time = datetime.strptime(end,"%H:%M:%S")
return self.start_time,self.end_time
def day_night_switch(self): #time_switch = 0 白盘标的,1为夜盘0:00前收盘的标的(如:rb),2为0:00后收盘的标的(如:ag,cu)
if self.start_time.time() < time(hour=20,minute=0):
self.time_switch = 0
elif self.end_time.time() > time(hour=3,minute=0):
self.time_switch = 1
else:
self.time_switch = 2
return self.time_switch
def trading_period(self,bar): #判断标的日内交易时间
DAY_START = time(hour=9,minute=0)
DAY_END = time(hour=14,minute=57)
if self.day_night_switch() == 0:
return bar.datetime.time() < (self.end_time + timedelta(minutes=-3)).time()
elif self.day_night_switch() == 1:
return bar.datetime.time() >= self.start_time.time() and bar.datetime.time() < (self.end_time + timedelta(minutes=-3)).time() \
or (bar.datetime.time() >= DAY_START and bar.datetime.time() < DAY_END )
else:
return bar.datetime.time() >= self.start_time.time() or bar.datetime.time() < (self.end_time + timedelta(minutes=-3)).time() \
or (bar.datetime.time() >= DAY_START and bar.datetime.time() < DAY_END )
2.trading_hour.json如下: #记录了期货白盘期货标的开收盘时间,夜盘标的夜盘开盘以及夜盘收盘时间,遇到特殊日子(比如疫情期间,ag没有夜盘了,那时间要修正“AG”:["9:30:00","15:00:00"]),直接过来修改开收盘时间即可
{
"IF":["9:30:00","15:00:00"],
"IC":["9:30:00","15:00:00"],
"IH":["9:30:00","15:00:00"],
"T":["9:30:00","15:15:00"],
"AU":["21:00:00","2:30:00"],
"AG":["21:00:00","2:30:00"],
"CU":["21:00:00","1:00:00"],
"AL":["21:00:00","1:00:00"],
"ZN":["21:00:00","1:00:00"],
"PB":["21:00:00","1:00:00"],
"NI":["21:00:00","1:00:00"],
"SN":["21:00:00","1:00:00"],
"RB":["21:00:00","23:00:00"],
"I":["21:00:00","23:00:00"],
"HC":["21:00:00","23:00:00"],
"SS":["21:00:00","1:00:00"],
"SF":["9:00:00","15:00:00"],
"SM":["9:00:00","15:00:00"],
"JM":["21:00:00","23:00:00"],
"J":["21:00:00","23:00:00"],
"ZC":["21:00:00","23:00:00"],
"FG":["21:00:00","23:00:00"],
"SP":["21:00:00","23:00:00"],
"FU":["21:00:00","23:00:00"],
"LU":["21:00:00","23:00:00"],
"SC":["21:00:00","2:30:00"],
"BU":["21:00:00","23:00:00"],
"PG":["21:00:00","23:00:00"],
"RU":["21:00:00","23:00:00"],
"NR":["21:00:00","23:00:00"],
"L":["21:00:00","23:00:00"],
"TA":["21:00:00","23:00:00"],
"V":["21:00:00","23:00:00"],
"EG":["21:00:00","23:00:00"],
"MA":["21:00:00","23:00:00"],
"PP":["21:00:00","23:00:00"],
"EB":["21:00:00","23:00:00"],
"UR":["9:00:00","15:00:00"],
"SA":["21:00:00","23:00:00"],
"C":["21:00:00","23:00:00"],
"A":["21:00:00","23:00:00"],
"CS":["21:00:00","23:00:00"],
"B":["21:00:00","23:00:00"],
"M":["21:00:00","23:00:00"],
"Y":["21:00:00","23:00:00"],
"RM":["21:00:00","23:00:00"],
"OI":["21:00:00","23:00:00"],
"P":["21:00:00","23:00:00"],
"CF":["21:00:00","23:00:00"],
"SR":["21:00:00","23:00:00"],
"JD":["9:00:00","15:00:00"],
"AP":["9:00:00","15:00:00"],
"CJ":["9:00:00","15:00:00"]
}
3.在自己的策略中import TRADINHOUR from vnpy.app.user_tools.trading_hour import TRADINGHOUR 同时import re
def --init--():加入
self.tradingtime = TRADINGHOUR()
self.symbol = "".join(re.findall(r"\D+",self.get_data()["vt_symbol"].split(".")[0])).upper() #获取标的代码
self.start_time,self.end_time = self.tradingtime.get_trading_time(self.symbol)
这些完成后,就可以在你的on_bar函数里面调用self.tradingtime.trading_period(bar)获取标的日内交易时段了
例如:def on_bar(self, bar: BarData):
###
###
if self.tradingtime.trading_period(bar): #获取当下交易标的日内交易时段,平仓时间设置为收盘前3min
if self.pos == 0:
###****
if self.pos > 0:
### ****
if self.pos < 0:
###*****
else: #收盘平仓
if self.pos > 0:
self.sell(bar.close_price *0.99, abs(self.pos))
elif self.pos < 0:
self.cover(bar.close_price*1.01, abs(self.pos))
1.同一策略,不同标的同时开盘前开启,开盘前总会出现没有数据更新情况,有时候延迟几分钟,今天延迟了差不多15min才更新(主逻辑在on_bar里面)
2.同一策略,夜盘标的在上述更新完成后,可以随时更新日内高低点,只有白盘的标的,日内高低点只能等到有仓位时候才能更新
注:区分白盘夜盘,自己建了一个json文件,存放标的开盘时间,比对json文件与 self.symol抓取开盘时间;单个标的测试打印开盘时间没问题
3.同一策略,不同标的,当某几个标的入场后手动平仓了,停止这几个标的对应的策略,依然在发出止损单,开仓单,这意味着没有停止该标的对应的策略啊
看了下tick数据订阅:ctatemplate 有on_tick
1.想着tick数据到底从哪儿获取的? main_engine.get_contract ----main_engine.subscribe-----geteway_subscribe----subscribe(pass),subscribe没有内容,那么tick数据怎么获得的推送?
均价线AVL指标,看了下arraymanager 、talib里面没有这个指标,如何自己实现?
1.看了下价差交易模块,和算法交易模块里面有网格算法,思考如何在价差交易模块里开发自己的网格策略,和用bisic_srpead_stategy.py一样,填入网格参数既可进行价差的网格交易;
2.如果自己写价差网格策略,应该放在价差策略 on_spread_tick ,还是on_spread_bar里面,on_spread_tick是组合价差的tickdata嘛?如果是的话可发开发价差的tick级别高频策略
股指期货,如果昨日2buy_k,2sell_kl锁仓,今日self.pos 是只净持仓,self.pos =0?
如上图,在每个buy,sell,short,cover后面补上lock=true就可以实现日内收盘净持仓为0,锁仓交易吗