VeighNa量化社区
你的开源社区量化交易平台
Member
avatar
加入于:
帖子: 19
声望: 18

RQData是付费产品,不是每个人都有付费的想法,这里是用天勤SDK的数据替换掉RQData的数据,因为天勤有限制,一次性只能抓取八千多条数据,而且无法指定下载某些日期范围内的数据,所以用于回测并不是很合适,但是实盘的时候,是很好的,可以补充策略初始化时候的数据。
用法:先备份vnpy\trader\rqdata.py这个文件,将以下代码保存文件为rqdata.py,替换掉原先的rqdata.py即可

pip install tqsdk
import pandas as pd
from tqsdk import TqApi
from datetime import timedelta
from typing import List, Optional

from .setting import SETTINGS
from .constant import Exchange, Interval
from .object import BarData, HistoryRequest

# 时间戳对齐
TIME_GAP = 8 * 60 * 60 * 1000000000
INTERVAL_VT2TQ = {
    Interval.MINUTE: 60,
    Interval.HOUR: 60 * 60,
    Interval.DAILY: 60 * 60 * 24,
}

class TianqinClient:
    """
    Client for querying history data from Tianqin.
    """

    def __init__(self):
        """"""
        self.inited: bool = False
        self.symbols: set = set()
        self.api = None

    def init(self) -> bool:
        """"""
        if self.inited:
            return True

        try:
            self.api = TqApi()
            # 获得全部合约
            self.symbols = [k for k, v in self.api._data["quotes"].items()]
        except:
            return False

        self.inited = True
        return True

    def to_tq_symbol(self, symbol: str, exchange: Exchange) -> str:
        """
        TQSdk exchange first
        """
        for count, word in enumerate(symbol):
            if word.isdigit():
                break

        # Check for index symbol
        time_str = symbol[count:]
        if time_str in ["88"]:
            return f"KQ.m@{exchange}.{symbol[:count]}"
        if time_str in ["99"]:
            return f"KQ.i@{exchange}.{symbol[:count]}"

        return f"{exchange.value}.{symbol}"

    def query_history(self, req: HistoryRequest) -> Optional[List[BarData]]:
        """
        Query history bar data from TqSdk.
        """
        symbol = req.symbol
        exchange = req.exchange
        interval = req.interval
        start = req.start
        end = req.end

        tq_symbol = self.to_tq_symbol(symbol, exchange)
        if tq_symbol not in self.symbols:
            return None

        tq_interval = INTERVAL_VT2TQ.get(interval)
        if not tq_interval:
            return None

        # For querying night trading period data
        end += timedelta(1)

        # Only query open interest for futures contract

        # 只能用来补充最新的数据,无法指定日期
        df = self.api.get_kline_serial(tq_symbol, tq_interval, 8000).sort_values(by=["datetime"])

        # 时间戳对齐
        df["datetime"] = pd.to_datetime(df["datetime"] + TIME_GAP)

        # 过滤开始结束时间
        df = df[(df['datetime'] >= start - timedelta(days=1)) & (df['datetime'] < end)]

        data: List[BarData] = []

        if df is not None:
            for ix, row in df.iterrows():
                bar = BarData(
                    symbol=symbol,
                    exchange=exchange,
                    interval=interval,
                    datetime=row["datetime"].to_pydatetime(),
                    open_price=row["open"],
                    high_price=row["high"],
                    low_price=row["low"],
                    close_price=row["close"],
                    volume=row["volume"],
                    open_interest=row.get("open_oi", 0),
                    gateway_name="TQ",
                )
                data.append(bar)
        return data

# 使用天勤SDK替换RQData,一次只能下载8000条数据,可以用于补充运行时的数据
RqdataClient = TianqinClient
rqdata_client = TianqinClient()
Member
avatar
加入于:
帖子: 41
声望: 3

很好的方法,谢谢分享!

Member
avatar
加入于:
帖子: 16
声望: 1

谢谢分享

Member
加入于:
帖子: 50
声望: 2

感谢 正需要这种方法用在实盘。回测用自己数据库的数据。 免费撸是王道

Member
avatar
加入于:
帖子: 2
声望: 0

谢谢

Member
avatar
加入于:
帖子: 22
声望: 2

对的, 实盘back fill的数据8000条绰绰有余了

Member
avatar
加入于:
帖子: 8
声望: 1

请问lz用的什么数据库?时间戳对齐的作用是?

Member
avatar
加入于:
帖子: 54
声望: 0

这个如何使用啊?我按照楼主的方法替换了,在使用simnow账号进行CTA策略加载初始化后总是报如下错误:
AtrRis: 触发异常已停止
Traceback (most recent call last):
File "d:\Anaconda3\lib\site-packages\vnpy\app\cta_strategy\engine.py", line 601, in call_strategy_func
func()
File "d:\Anaconda3\lib\site-packages\vnpy\app\cta_strategy\strategies\atr_rsi_strategy.py", line 66, in on_init
self.load_bar(10)
File "d:\Anaconda3\lib\site-packages\vnpy\app\cta_strategy\template.py", line 245, in load_bar
use_database
File "d:\Anaconda3\lib\site-packages\vnpy\app\cta_strategy\engine.py", line 556, in load_bar
bars = self.query_bar_from_rq(symbol, exchange, interval, start, end)
File "d:\Anaconda3\lib\site-packages\vnpy\app\cta_strategy\engine.py", line 145, in query_bar_from_rq
data = rqdata_client.query_history(req)
File "d:\Anaconda3\lib\site-packages\vnpy\trader\rqdata.py", line 138, in query_history
if rq_symbol not in self.symbols:
TypeError: argument of type 'NoneType' is not iterable

无法初始化,高手教下是如何原因???

Member
avatar
加入于:
帖子: 6
声望: 0

wrote:

RQData是付费产品,不是每个人都有付费的想法,这里是用天勤SDK的数据替换掉RQData的数据,因为天勤有限制,一次性只能抓取八千多条数据,而且无法指定下载某些日期范围内的数据,所以用于回测并不是很合适,但是实盘的时候,是很好的,可以补充策略初始化时候的数据。
用法:先备份vnpy\trader\rqdata.py这个文件,将以下代码保存文件为rqdata.py,替换掉原先的rqdata.py即可

pip install tqsdk
import pandas as pd
from tqsdk import TqApi
from datetime import timedelta
from typing import List, Optional

from .setting import SETTINGS
from .constant import Exchange, Interval
from .object import BarData, HistoryRequest

# 时间戳对齐
TIME_GAP = 8 * 60 * 60 * 1000000000
INTERVAL_VT2TQ = {
    Interval.MINUTE: 60,
    Interval.HOUR: 60 * 60,
    Interval.DAILY: 60 * 60 * 24,
}

class TianqinClient:
    """
    Client for querying history data from Tianqin.
    """

    def __init__(self):
        """"""
        self.inited: bool = False
        self.symbols: set = set()
        self.api = None

    def init(self) -> bool:
        """"""
        if self.inited:
            return True

        try:
            self.api = TqApi()
            # 获得全部合约
            self.symbols = [k for k, v in self.api._data["quotes"].items()]
        except:
            return False

        self.inited = True
        return True

    def to_tq_symbol(self, symbol: str, exchange: Exchange) -> str:
        """
        TQSdk exchange first
        """
        for count, word in enumerate(symbol):
            if word.isdigit():
                break

        # Check for index symbol
        time_str = symbol[count:]
        if time_str in ["88"]:
            return f"KQ.m@{exchange}.{symbol[:count]}"
        if time_str in ["99"]:
            return f"KQ.i@{exchange}.{symbol[:count]}"

        return f"{exchange.value}.{symbol}"

    def query_history(self, req: HistoryRequest) -> Optional[List[BarData]]:
        """
        Query history bar data from TqSdk.
        """
        symbol = req.symbol
        exchange = req.exchange
        interval = req.interval
        start = req.start
        end = req.end

        tq_symbol = self.to_tq_symbol(symbol, exchange)
        if tq_symbol not in self.symbols:
            return None

        tq_interval = INTERVAL_VT2TQ.get(interval)
        if not tq_interval:
            return None

        # For querying night trading period data
        end += timedelta(1)

        # Only query open interest for futures contract

        # 只能用来补充最新的数据,无法指定日期
        df = self.api.get_kline_serial(tq_symbol, tq_interval, 8000).sort_values(by=["datetime"])

        # 时间戳对齐
        df["datetime"] = pd.to_datetime(df["datetime"] + TIME_GAP)

        # 过滤开始结束时间
        df = df[(df['datetime'] >= start - timedelta(days=1)) & (df['datetime'] < end)]

        data: List[BarData] = []

        if df is not None:
            for ix, row in df.iterrows():
                bar = BarData(
                    symbol=symbol,
                    exchange=exchange,
                    interval=interval,
                    datetime=row["datetime"].to_pydatetime(),
                    open_price=row["open"],
                    high_price=row["high"],
                    low_price=row["low"],
                    close_price=row["close"],
                    volume=row["volume"],
                    open_interest=row.get("open_oi", 0),
                    gateway_name="TQ",
                )
                data.append(bar)
        return data

# 使用天勤SDK替换RQData,一次只能下载8000条数据,可以用于补充运行时的数据
RqdataClient = TianqinClient
rqdata_client = TianqinClient()

楼主,CTP实盘时,为什么不能用vnpy自己记录的数据进行策略初始化,而非要外部的数据源进行初始化,请指教?

Member
avatar
加入于:
帖子: 5
声望: 0

感谢。
open_interest=row.get("open_oi", 0) 的 open_oi 是不是考虑改用 close_oi ?

Member
avatar
加入于:
帖子: 11
声望: 0

我也使用这个方法,点初始化按钮后,一直不结束,无法点击启动按钮?

Member
avatar
加入于:
帖子: 11
声望: 0

用vnpy中的demo策略 也有这个问题

Member
avatar
加入于:
帖子: 11
声望: 0

原来好像成功过,是不是vnpy版本更新后才不行呢?

Member
加入于:
帖子: 50
声望: 2

2.11版本是没问题的。2.14版本 下载数据就会报错··,不知道 楼主大大 能不能更新一版

Member
avatar
加入于:
帖子: 25
声望: 1

看来 一旦功能调通了,就不要再升级了.

Member
avatar
加入于:
帖子: 35
声望: 0

测试过了,确实不行,出现错误。

Member
avatar
加入于:
帖子: 4
声望: 0

回测猛如虎 wrote:

感谢 正需要这种方法用在实盘。回测用自己数据库的数据。 免费撸是王道
请教一下 回测数据是哪里搞的呀

Member
avatar
加入于:
帖子: 4
声望: 0

回测猛如虎 wrote:

感谢 正需要这种方法用在实盘。回测用自己数据库的数据。 免费撸是王道
请教一下 回测数据是哪里搞的呀

Member
avatar
加入于:
帖子: 8
声望: 0

请问现在还有8000条的限制吗?我看官方给的帮助文档里面的示例,可以指定日期下载数据啊。tick数据也有就是清洗有点麻烦

Member
avatar
加入于:
帖子: 1
声望: 0

感谢楼主

© 2015-2022 上海韦纳软件科技有限公司
备案服务号:沪ICP备18006526号

沪公网安备 31011502017034号

【用户协议】
【隐私政策】
【免责条款】