首先感谢tonywang_efun
https://www.vnpy.com/forum/topic/1472-ju-kuan-shu-ju-jddatasdk-ji-cheng-fang-an-qi-chang-da-yi-nian
直接上方案:
1、在site-packages目录下新建文件夹vnpy_jqdata
2、在vnpy_jqdata目录下,新建init.py
3、在vnpy_jqdata目录下,新建jqdata_datafeed.py
代码:
init.py
import importlib_metadata
from .jqdata_datafeed import JqdataDatafeed as Datafeed
try:
__version__ = importlib_metadata.version("vnpy_jqdata")
except importlib_metadata.PackageNotFoundError:
__version__ = "dev"
jqdata_datafeed.py代码:
import jqdatasdk as jq
from datetime import timedelta, datetime
import datetime
from typing import List
from vnpy.trader.constant import Exchange, Interval
# from vnpy.trader.mddata.dataapi import MdDataApi
from vnpy.trader.datafeed import BaseDatafeed
from vnpy.trader.object import BarData, HistoryRequest
from vnpy.trader.setting import SETTINGS
from pytz import timezone
CHINA_TZ = timezone("Asia/Shanghai")
INTERVAL_VT2JQ = {
Interval.MINUTE: '1m',
Interval.HOUR: '60m',
Interval.DAILY: '1d',
}
INTERVAL_ADJUSTMENT_MAP_JQ = {
Interval.MINUTE: timedelta(minutes=1),
Interval.HOUR: timedelta(hours=1),
Interval.DAILY: timedelta() # no need to adjust for daily bar
}
class JqdataDatafeed(BaseDatafeed):
"""聚宽JQData客户端封装类"""
def __init__(self):
""""""
self.username = SETTINGS["jqdata.username"]
self.password = SETTINGS["jqdata.password"]
self.inited = False
def init(self, username="", password=""):
""""""
if self.inited:
return True
if username and password:
self.username = username
self.password = password
if not self.username or not self.password:
return False
try:
jq.auth(self.username, self.password)
except Exception as ex:
print("jq auth fail:" + repr(ex))
return False
self.inited = True
return True
def to_jq_symbol(self, symbol: str, exchange: Exchange):
"""
CZCE product of RQData has symbol like "TA1905" while
vt symbol is "TA905.CZCE" so need to add "1" in symbol.
"""
if exchange in [Exchange.SSE, Exchange.SZSE]:
if exchange == Exchange.SSE:
jq_symbol = f"{symbol}.XSHG" # 上海证券交易所
else:
jq_symbol = f"{symbol}.XSHE" # 深圳证券交易所
elif exchange == Exchange.SHFE:
jq_symbol = f"{symbol}.XSGE" # 上期所
elif exchange == Exchange.CFFEX:
jq_symbol = f"{symbol}.CCFX" # 中金所
elif exchange == Exchange.DCE:
jq_symbol = f"{symbol}.XDCE" # 大商所
elif exchange == Exchange.INE:
jq_symbol = f"{symbol}.XINE" # 上海国际能源期货交易所
elif exchange == Exchange.CZCE:
# 郑商所 的合约代码年份只有三位 需要特殊处理
for count, word in enumerate(symbol):
if word.isdigit():
break
# Check for index symbol
time_str = symbol[count:]
if time_str in ["88", "888", "99", "8888", "9999"]:
return f"{symbol}.XZCE"
# noinspection PyUnboundLocalVariable
product = symbol[:count]
year = symbol[count]
month = symbol[count + 1:]
if year == "9":
year = "1" + year
else:
year = "2" + year
jq_symbol = f"{product}{year}{month}.XZCE"
return jq_symbol.upper()
def query_bar_history(self, req: HistoryRequest):
"""
Query history bar data from JQData.
"""
symbol = req.symbol
exchange = req.exchange
interval = req.interval
start = req.start
end = req.end
jq_symbol = self.to_jq_symbol(symbol, exchange)
# if jq_symbol not in self.symbols:
# return None
jq_interval = INTERVAL_VT2JQ.get(interval)
if not jq_interval:
return None
# For adjust timestamp from bar close point (RQData) to open point (VN Trader)
# adjustment = INTERVAL_ADJUSTMENT_MAP_JQ.get(interval)
adjustment = INTERVAL_ADJUSTMENT_MAP_JQ[interval]
# For querying night trading period data
end += timedelta(1)
df = jq.get_price(
jq_symbol,
frequency=jq_interval,
fields=["open", "high", "low", "close", "volume"],
start_date=start,
end_date=end,
skip_paused=True,
)
data: List[BarData] = []
if df is not None:
for ix, row in df.iterrows():
bar = BarData(
symbol=symbol,
exchange=exchange,
interval=interval,
datetime=row.name.to_pydatetime() - adjustment,
open_price=row["open"],
high_price=row["high"],
low_price=row["low"],
close_price=row["close"],
volume=row["volume"],
gateway_name="JQ"
)
data.append(bar)
return data
winsoning wrote:
一样遇到该问题,我是下单里逻辑是里有self.pos判断的,满足策略条件,并且如果空仓,就下单,第一次下单后,没有来的及改变pos的值,等下一个tick过来后,就重复下单:,解决该问题就是自己创建一个变量,来存pos值得,比如:new_pos ,下单前,先维护这个变量,等下个tick进来后,就用这个变量处理逻辑。
大神能给个参考代码吗?万分感谢🙏
感谢解答,我再研究研究~~
郭易燔 wrote:
如果还是不行,在template.py中203行的short函数中打印一下Direction.SHORT, Offset.OPEN, price, volume, stop, lock, net,看一下是多加了哪个参数
还是一样的。。。但是如果把 site-packages\vnpy_ctastrategytemplate.py 替换为 vnpy-2.1.8 版本的,就能开单。。有点奇怪
郭易燔 wrote:
111行,改成self.buy(bar.close_price, self.fixed_size, stop=True)试试,不太清楚你这个True是指哪个参数,如果是lock或者net的话,把stop换掉
多谢,我再试下
求高手帮忙看下,多谢~~
错误提示:
触发异常已停止
Traceback (most recent call last):
File ""c:\vnstudio\lib\site-packages\vnpy_ctastrategy\engine.py"", line 609, in call_strategy_func
func(params)
File ""C:\Users\lxero-VV\strategies\divo_X.py"", line 83, in on_tick
self.bg_5min.update_tick(tick)
File ""c:\vnstudio\lib\site-packages\vnpy\trader\utility.py"", line 224, in update_tick
self.on_bar(self.bar)
File ""C:\Users\lxero-VV\strategies\divo_X.py"", line 90, in on_bar
self.bg_5min.update_bar(bar)
File ""c:\vnstudio\lib\site-packages\vnpy\trader\utility.py"", line 268, in update_bar
self.update_bar_minute_window(bar)
File ""c:\vnstudio\lib\site-packages\vnpy\trader\utility.py"", line 308, in update_bar_minute_window
self.on_window_bar(self.window_bar)
File ""C:\Users\lxero-VV\strategies\divo_X.py"", line 119, in on_5min_bar
self.short(fall_trader_price, self.fixed_size)
File ""c:\vnstudio\lib\site-packages\vnpy_ctastrategy\template.py"", line 211, in short
net
File ""c:\vnstudio\lib\site-packages\vnpy_ctastrategy\template.py"", line 250, in send_order
self, direction, offset, price, volume, stop, lock, net
TypeError: send_order() takes 8 positional arguments but 9 were given
"
部分代码:
if self.pos == 0:
if self.rise_up:
self.buy(bar.close_price + 2, self.fixed_size)
elif self.fall_down:
self.short(bar.close_price - 2, self.fixed_size)
else:
pass
if self.pos > 0:
if self.fall_down:
self.sell(bar.close_price - 2, abs(self.pos))
self.short(bar.close_price - 2, self.fixed_size)
else:
pass
if self.pos < 0:
if self.rise_up:
self.cover(bar.close_price + 2, abs(self.pos))
self.buy(bar.close_price + 2, self.fixed_size)
else:
pass
多谢~~