[Add] download bar data from gateway in CtaBacktester

This commit is contained in:
vn.py 2019-05-08 15:39:15 +08:00
parent e1c824307e
commit 8c707435e8
5 changed files with 108 additions and 14 deletions

View File

@ -258,7 +258,7 @@ class RestClient(object):
request.response = response
status_code = response.status_code
if status_code / 100 == 2: # 2xx都算成功尽管交易所都用200
if status_code // 100 == 2: # 2xx都算成功尽管交易所都用200
jsonBody = response.json()
request.callback(jsonBody, request)
request.status = RequestStatus.success

View File

@ -9,6 +9,7 @@ from vnpy.event import Event, EventEngine
from vnpy.trader.engine import BaseEngine, MainEngine
from vnpy.trader.constant import Interval
from vnpy.trader.utility import extract_vt_symbol
from vnpy.trader.object import HistoryRequest
from vnpy.trader.rqdata import rqdata_client
from vnpy.trader.database import database_manager
from vnpy.app.cta_strategy import (
@ -337,7 +338,22 @@ class BacktesterEngine(BaseEngine):
"""
self.write_log(f"{vt_symbol}-{interval}开始下载历史数据")
contract = self.main_engine.get_contract(vt_symbol)
# If history data provided in gateway, then query
if contract and contract.history_data:
req = HistoryRequest(
symbol=contract.symbol,
exchange=contract.exchange,
interval=Interval(interval),
start=start,
end=end
)
data = self.main_engine.query_history(req, contract.gateway_name)
# Otherwise use RQData to query data
else:
symbol, exchange = extract_vt_symbol(vt_symbol)
data = rqdata_client.query_bar(
symbol, exchange, Interval(interval), start, end
)

View File

@ -56,14 +56,14 @@ class BacktesterManager(QtWidgets.QWidget):
self.class_combo = QtWidgets.QComboBox()
self.class_combo.addItems(self.class_names)
self.symbol_line = QtWidgets.QLineEdit("IF88.CFFEX")
self.symbol_line = QtWidgets.QLineEdit("XBTUSD.BITMEX")
self.interval_combo = QtWidgets.QComboBox()
for inteval in Interval:
self.interval_combo.addItem(inteval.value)
end_dt = datetime.now()
start_dt = end_dt - timedelta(days=3 * 365)
start_dt = end_dt - timedelta(days=30)# * 365)
self.start_date_edit = QtWidgets.QDateEdit(
QtCore.QDate(

View File

@ -7,7 +7,7 @@ import hmac
import sys
import time
from copy import copy
from datetime import datetime
from datetime import datetime, timedelta
from threading import Lock
from urllib.parse import urlencode
@ -21,7 +21,8 @@ from vnpy.trader.constant import (
OrderType,
Product,
Status,
Offset
Offset,
Interval
)
from vnpy.trader.gateway import BaseGateway
from vnpy.trader.object import (
@ -31,6 +32,7 @@ from vnpy.trader.object import (
PositionData,
AccountData,
ContractData,
BarData,
OrderRequest,
CancelRequest,
SubscribeRequest,
@ -61,6 +63,18 @@ ORDERTYPE_VT2BITMEX = {
}
ORDERTYPE_BITMEX2VT = {v: k for k, v in ORDERTYPE_VT2BITMEX.items()}
INTERVAL_VT2BITMEX = {
Interval.MINUTE: "1m",
Interval.HOUR: "1h",
Interval.DAILY: "1d",
}
TIMEDELTA_MAP = {
Interval.MINUTE: timedelta(minutes=1),
Interval.HOUR: timedelta(hours=1),
Interval.DAILY: timedelta(days=1),
}
class BitmexGateway(BaseGateway):
"""
@ -160,7 +174,7 @@ class BitmexRestApi(RestClient):
Generate BitMEX signature.
"""
# Sign
expires = int(time.time() + 5)
expires = int(time.time() + 30)
if request.params:
query = urlencode(request.params)
@ -286,7 +300,72 @@ class BitmexRestApi(RestClient):
def query_history(self, req: HistoryRequest):
""""""
pass
history = []
count = 750
start_time = req.start.isoformat()
while True:
# Create query params
params = {
"binSize": INTERVAL_VT2BITMEX[req.interval],
"symbol": req.symbol,
"count": count,
"startTime": start_time
}
# Add end time if specified
if req.end:
params["endTime"] = req.end.isoformat()
# Get response from server
resp = self.request(
"GET",
"/trade/bucketed",
params=params
)
# Break if request failed with other status code
if resp.status_code // 100 != 2:
msg = f"获取历史数据失败,状态码:{resp.status_code},信息:{resp.text}"
self.gateway.write_log(msg)
break
else:
data = resp.json()
for d in data:
dt = datetime.strptime(d["timestamp"], "%Y-%m-%dT%H:%M:%S.%fZ")
bar = BarData(
symbol=req.symbol,
exchange=req.exchange,
datetime=dt,
interval=req.interval,
volume=d["volume"],
open_price=d["open"],
high_price=d["high"],
low_price=d["low"],
close_price=d["close"],
gateway_name=self.gateway_name
)
history.append(bar)
begin = data[0]["timestamp"]
end = data[-1]["timestamp"]
msg = f"获取历史数据成功,{req.symbol} - {req.interval.value}{begin} - {end}"
self.gateway.write_log(msg)
# Break if total data count less than 750 (latest date collected)
if len(data) < 750:
break
# Update start time
start_time = bar.datetime + TIMEDELTA_MAP[req.interval]
return history
def on_send_order_failed(self, status_code: str, request: Request):
"""
@ -624,7 +703,7 @@ class BitmexWebsocketApi(WebsocketClient):
size=d["lotSize"],
stop_supported=True,
net_position=True,
bar_history=True,
history_data=True,
gateway_name=self.gateway_name,
)

View File

@ -236,8 +236,7 @@ class ContractData(BaseData):
min_volume: float = 1 # minimum trading volume of the contract
stop_supported: bool = False # whether server supports stop order
net_position: bool = False # whether gateway uses net position volume
bar_history: bool = False # whether gateway provides bar history data
tick_history: bool = False # whether gateway provides tick history data
history_data: bool = False # whether gateway provides bar history data
option_strike: float = 0
option_underlying: str = "" # vt_symbol of underlying contract