[Add] download bar data from gateway in CtaBacktester
This commit is contained in:
parent
e1c824307e
commit
8c707435e8
@ -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
|
||||
|
@ -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,10 +338,25 @@ class BacktesterEngine(BaseEngine):
|
||||
"""
|
||||
self.write_log(f"{vt_symbol}-{interval}开始下载历史数据")
|
||||
|
||||
symbol, exchange = extract_vt_symbol(vt_symbol)
|
||||
data = rqdata_client.query_bar(
|
||||
symbol, exchange, Interval(interval), start, end
|
||||
)
|
||||
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
|
||||
)
|
||||
|
||||
if data:
|
||||
database_manager.save_bar_data(data)
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
)
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user