def refresh_tree(self) -> None: """""" self.clear_tree() data = self.engine.get_bar_data_available() for d in data: key = (d["symbol"], d["exchange"], d["interval"]) item = self.tree_items.get(key, None) if not item: item = QtWidgets.QTreeWidgetItem() self.tree_items[key] = item item.setText(1, ".".join([d["symbol"], d["exchange"]])) item.setText(2, d["symbol"]) item.setText(3, d["exchange"]) if d["interval"] == Interval.MINUTE.value: self.minute_child.addChild(item) elif d["interval"] == Interval.HOUR.value: self.hour_child.addChild(item) else: self.daily_child.addChild(item) output_button = QtWidgets.QPushButton("导出") output_func = partial(self.output_data, d["symbol"], Exchange(d["exchange"]), Interval(d["interval"]), d["start"], d["end"]) output_button.clicked.connect(output_func) show_button = QtWidgets.QPushButton("查看") show_func = partial(self.show_data, d["symbol"], Exchange(d["exchange"]), Interval(d["interval"]), d["start"], d["end"]) show_button.clicked.connect(show_func) delete_button = QtWidgets.QPushButton("删除") delete_func = partial( self.delete_data, d["symbol"], Exchange(d["exchange"]), Interval(d["interval"]), ) delete_button.clicked.connect(delete_func) self.tree.setItemWidget(item, 7, show_button) self.tree.setItemWidget(item, 8, output_button) self.tree.setItemWidget(item, 9, delete_button) item.setText(4, str(d["count"])) item.setText(5, d["start"].strftime("%Y-%m-%d %H:%M:%S")) item.setText(6, d["end"].strftime("%Y-%m-%d %H:%M:%S")) self.minute_child.setExpanded(True) self.hour_child.setExpanded(True) self.daily_child.setExpanded(True)
def get_bar_data_available(self) -> List[Dict]: """""" data = database_manager.get_bar_data_statistics() for d in data: oldest_bar = database_manager.get_oldest_bar_data( d["symbol"], Exchange(d["exchange"]), Interval(d["interval"])) d["start"] = oldest_bar.datetime newest_bar = database_manager.get_newest_bar_data( d["symbol"], Exchange(d["exchange"]), Interval(d["interval"])) d["end"] = newest_bar.datetime return data
def load_tick_data( self, symbol: str, exchange: Exchange, start: datetime, end: datetime ) -> List[TickData]: """读取TICK数据""" filter = { "symbol": symbol, "exchange": exchange.value, "datetime": { "$gte": start, "$lte": end } } c: Cursor = self.tick_collection.find(filter) ticks = [] for d in c: d["exchange"] = Exchange(d["exchange"]) d["gateway_name"] = "DB" d.pop("_id") tick = TickData(**d) ticks.append(tick) return ticks
def load_bar_data( self, symbol: str, exchange: Exchange, interval: Interval, start: datetime, end: datetime ) -> List[BarData]: """读取K线数据""" filter = { "symbol": symbol, "exchange": exchange.value, "interval": interval.value, "datetime": { "$gte": start, "$lte": end } } c: Cursor = self.bar_collection.find(filter) bars = [] for d in c: d["exchange"] = Exchange(d["exchange"]) d["interval"] = Interval(d["interval"]) d["gateway_name"] = "DB" d.pop("_id") bar = BarData(**d) bars.append(bar) return bars
def to_opbasic(self): """ Generate OptionsBasic object from DbOpitonsBasic. """ opbasic = OptionsBasic( symbol=self.symbol, exchange=Exchange(self.exchange), name=self.name, per_unit=self.per_unit, opt_code=self.opt_code, opt_type=self.opt_type, call_put=self.call_put, exercise_type=self.exercise_type, exercise_price=self.exercise_price, s_month=self.s_month, maturity_date=self.maturity_date, list_price=self.list_price, list_date=self.list_date, delist_date=self.delist_date, last_edate=self.last_edate, last_ddate=self.last_ddate, quote_unit=quote_unit, min_price_chg=self.min_price_chg, gateway_name="DB", ) return opbasic
def set_parameters( self, vt_symbol: str, interval: Interval, rate: float, slippage: float, size: float, pricetick: float, enginetype: EngineType, capital: int = 0, mode: BacktestingMode = BacktestingMode.BAR, inverse: bool = False, risk_free: float = 0, annual_days: int = 240 ): """""" self.mode = mode self.vt_symbol = vt_symbol self.interval = Interval(interval) self.rate = rate self.slippage = slippage self.size = size self.pricetick = pricetick self.enginetype = enginetype self.symbol, exchange_str = self.vt_symbol.split(".") self.exchange = Exchange(exchange_str) self.capital = capital self.mode = mode self.inverse = inverse self.risk_free = risk_free self.annual_days = annual_days
def main(): print("实盘交易") # 事件引擎 event_engine = EventEngine() # 把事件引擎附加到主引擎里 main_engine = MainEngine(event_engine) main_engine.write_log("主引擎创建成功") main_engine.add_gateway(OkexfGateway) # 获取所有交易通道 gateway_names = main_engine.get_all_gateway_names() for name in gateway_names: # 连接火币平台 connect = ConnectExchange(main_engine=main_engine, gateway_name=name) connect.connect() sleep(2) setting = load_json(filename="jyx_data_recorder_setting.json") vt_symbols = setting["vt_symbols"] functions = [] for vt_symbol in vt_symbols: gevent.sleep(1) # 交易对, 交易所 symbol, exchange_str = vt_symbol.split(".") exchange = Exchange(exchange_str) gateway = main_engine.get_gateway(exchange_str) functions += start_gevent(gateway=gateway, symbol=symbol, exchange=exchange) gevent.joinall(functions)
def load_trade_data(self, filter: dict) -> defaultdict(TradeData): """加载交易记录""" if self.trade_data_collection.count_documents(filter) == 0: self.output("无符合条件的交易记录") return else: trades = defaultdict(TradeData) c: Cursor = self.trade_data_collection.find(filter) for d in c: d["exchange"] = Exchange(d["exchange"]) d["direction"] = Direction(d["direction"]) d["offset"] = Offset(d["offset"]) d["gateway_name"] = "DB" d.pop("_id") trade = TradeData(**d) trades[d["tradeid"]] = trade start = self.trade_data_collection.find_one(sort=[("datetime", 1)])["datetime"] end = self.trade_data_collection.find_one(sort=[("datetime", -1)])["datetime"] self.output( f"已从{self.trade_db.name}{self.trade_data_collection.name}加载{start}至{end}交易记录{len(trades)}条" ) return trades
def load_bar_data(self, filter: dict) -> List[BarData]: """加载历史数据""" if self.bar_collection.count_documents(filter) == 0: self.output("无符合条件的历史数据") return else: bars = [] c: Cursor = self.bar_collection.find(filter) for d in c: d["exchange"] = Exchange(d["exchange"]) d["interval"] = Interval(d["interval"]) d["gateway_name"] = "DB" d.pop("_id") bar = BarData(**d) bars.append(bar) bars = sorted(bars, key=lambda bar: bar.datetime) self.output( f"已从{self.history_db.name}库{self.bar_collection.name}集合加载{bars[0].datetime}至{bars[-1].datetime}K线数据{len(bars)}条" ) return bars
def init_tick_database(self, vt_symbol: str): """初始化历史tick数据库""" symbol, exchange_str = vt_symbol.split(".") exchange = Exchange(exchange_str) db_name = f"{exchange.value}历史数据" db_names = self.client.list_database_names() if db_name in db_names: self.output(f"已有{db_name}数据库,现在开始初始化") else: self.output(f"当前不存在{db_name}数据库,开始创建新的数据库") # 初始化K线数据库 self.history_db: Database = self.client[db_name] collection_name = f"{symbol}_tick_data" collection_names = self.history_db.list_collection_names() if collection_name in collection_names: self.output(f"已有{collection_name}集合,现在开始初始化") else: self.output(f"当前不存在{collection_name}集合,开始创建新的集合") # 初始化Tick数据表 self.tick_collection: Collection = self.history_db[collection_name] self.tick_collection.create_index([ ("exchange", ASCENDING), ("symbol", ASCENDING), ("datetime", ASCENDING), ], unique=True) self.output(f"已完成{db_name}数据库{collection_name}集合初始化")
def query_bar_from_rq(self, vt_symbol: str, interval: Interval, start: datetime, end: datetime): """ Query bar data from RQData. """ symbol, exchange_str = vt_symbol.split(".") if symbol.upper() not in self.rq_symbols: return None df = self.rq_client.get_price( symbol.upper(), frequency=interval.value, fields=["open", "high", "low", "close", "volume"], start_date=start, end_date=end) data = [] for ix, row in df.iterrows(): bar = BarData(symbol=symbol, exchange=Exchange(exchange_str), interval=interval, datetime=row.name.to_pydatetime(), open_price=row["open"], high_price=row["high"], low_price=row["low"], close_price=row["close"], volume=row["volume"], gateway_name="RQ") data.append(bar) return data
def set_parameters(self, vt_symbol: str, interval: Interval, start: datetime, rate: float, slippage: float, size: float, pricetick: float, capital: int = 0, end: datetime = None, annual_days: int = 240): """""" self.vt_symbol = vt_symbol self.rate = rate self.slippage = slippage self.size = size self.start = start self.symbol, exchange_str = self.vt_symbol.split(".") self.exchange = Exchange(exchange_str) self.capital = capital self.end = end self.annual_days = annual_days
def gen_task_detail(self, objs: Sequence["DownloadTaskData"]): task_detail_list = [] for t in objs: startdate = datetime(t.startdate.year, t.startdate.month, t.startdate.day, 9) enddate = datetime(t.enddate.year, t.enddate.month, t.enddate.day, 16) daydate = startdate while daydate < enddate: if daydate.weekday() not in [5, 6]: task_detail = DownloadTaskDetailData( maintype=MainType(t.maintype), symbol=t.symbol, exchange=Exchange(t.exchange), interval=t.interval, detaildate=daydate, status=TaskStatus.INIT, processdate=datetime.now(), breakpointdate=datetime.now(), ) task_detail_list.append(task_detail) daydate += timedelta(days=1) self.update_task(t.maintype, t.symbol, t.exchange, t.interval, t.startdate, t.enddate, TaskStatus.FINISHED) ds = [ self.class_task_detail.from_task_detail(i) for i in task_detail_list ] self.class_task_detail.save_all(ds)
def load_ticks(self, csv_path: str): ticks = [] with codecs.open(csv_path, "r", "utf-8") as f: reader = csv.DictReader(f) for item in reader: dt = datetime.strptime(item['datetime'], '%Y-%m-%d %H:%M:%S') tick = TickData( symbol=item['symbol'], exchange=Exchange(item['exchange']), datetime=dt, name=item['name'], volume=self.covertf(item['volume']), open_interest=self.covertf(item['open_interest']), last_price=self.covertf(item['last_price']), last_volume=self.covertf(item['last_volume']), limit_up=self.covertf(item['limit_up']), limit_down=self.covertf(item['limit_down']), open_price=self.covertf(item['open_price']), high_price=self.covertf(item['high_price']), low_price=self.covertf(item['low_price']), pre_close=self.covertf(item['pre_close']), bid_price_1=self.covertf(item['bid_price_1']), ask_price_1=self.covertf(item['ask_price_1']), bid_volume_1=self.covertf(item['bid_volume_1']), ask_volume_1=self.covertf(item['ask_volume_1']), gateway_name="JQ") ticks.append(tick) return ticks
def generateVtBar(row, symbol, exchange): """生成K线""" bar = BarData(symbol=symbol, exchange=Exchange(exchange), interval=Interval.MINUTE, open_price=row["open"], high_price=row["high"], low_price=row["low"], close_price=row["close"], volume=row["volume"], datetime=row.name.to_pydatetime(), gateway_name="DB") bar.date = bar.datetime.strftime("%Y%m%d") bar.time = bar.datetime.strftime("%H%M%S") # 将bar的时间改成提前一分钟 hour = bar.time[0:2] minute = bar.time[2:4] sec = bar.time[4:6] if minute == "00": minute = "59" h = int(hour) if h == 0: h = 24 hour = str(h - 1).rjust(2, '0') else: minute = str(int(minute) - 1).rjust(2, '0') bar.time = hour + minute + sec bar.datetime = bar.datetime.strptime(' '.join([bar.date, bar.time]), '%Y%m%d %H%M%S') return bar
def __init__(self, index_code: str, desc: str, trace_code: str, start_date: datetime, type: IndexType, cal_sr=True, cal_close=True, cal_finance=True, rolling_gap_year=7): self.index_code = index_code self.symbol = index_code.split('.')[0] self.alias = index_code.split('.')[1] self.exchange = Exchange.get_exchange_by_alias(self.alias) self.desc = desc self.trace_code = trace_code self.start_date = start_date self.type = type self.cal_sr = cal_sr self.cal_close = cal_close self.cal_finance = cal_finance self.rolling_gap_year = rolling_gap_year if datetime.datetime.now() - start_date < datetime.timedelta( days=365 * rolling_gap_year): raise Exception("当前日期至指数成立时间小于滑动计算周期")
def to_trade_date(self): trade_date = TradeDate( exchange=Exchange(self.exchange), cal_date=self.cal_date, is_open=self.is_open, ) return trade_date
def set_parameters(self, vt_symbol: str, interval: Interval, start: datetime, rate: float, slippage: float, size: float, pricetick: float, capital: int = 0, end: datetime = None, mode: BacktestingMode = BacktestingMode.BAR, inverse: bool = False, risk_free: float = 0): """""" self.mode = mode self.vt_symbol = vt_symbol self.interval = Interval(interval) self.rate = rate self.slippage = slippage self.size = size self.pricetick = pricetick self.start = start self.symbol, exchange_str = self.vt_symbol.split(".") self.exchange = Exchange(exchange_str) self.capital = capital self.end = end self.mode = mode self.inverse = inverse self.risk_free = risk_free
def run_single_backtesting(args): engine = BacktestingEngine() req = HistoryRequest(symbol=args.symbol, exchange=Exchange(args.exchange), interval=Interval(args.interval), start=datetime.strptime(args.startdate, '%Y-%m-%d'), end=datetime.strptime(args.enddate, '%Y-%m-%d')) setting = txt_to_dic(args.backtesting_setting_file) strategy_class = STRATEGIES[args.strategy_class] engine.set_parameters(vt_symbol=req.vt_symbol, interval=req.interval, start=req.start, end=req.end, rate=args.rate, slippage=args.slippage, size=args.size, pricetick=args.pricetick, capital=args.capital) engine.add_strategy(strategy_class, setting) engine.load_data() engine.run_backtesting() df = engine.calculate_result() engine.calculate_statistics(df) engine.show_chart(df)
def load_tick_data( self, symbol: str, exchange: Exchange, start: datetime, end: datetime ) -> List[TickData]: """""" s: ModelSelect = ( DbTickData.select().where( (DbTickData.symbol == symbol) & (DbTickData.exchange == exchange.value) & (DbTickData.datetime >= start) & (DbTickData.datetime <= end) ).order_by(DbTickData.datetime) ) vt_symbol = f"{symbol}.{exchange.value}" ticks: List[TickData] = [] for db_tick in s: db_tick.datetime = DB_TZ.localize(db_tick.datetime) db_tick.exchange = Exchange(db_tick.exchange) db_tick.gateway_name = "DB" db_tick.vt_symbol = vt_symbol ticks.append(db_tick) return ticks
def downloadAllMinuteBar(self, days=0): """下载所有配置中的合约的分钟线数据""" if days == 0: days = self.setting["days"] startDt = datetime.today() - days * timedelta(1) enddt = datetime.today() print('-' * 50) print(u'开始下载合约分钟线数据') print('-' * 50) if 'Bar.Min' in self.setting: l = self.setting["Bar.Min"] for VNSymbol in l: dt0 = time.process_time() symbol = VNSymbol.split(".")[0] exchange = Exchange(VNSymbol.split(".")[1]) self.query_history(symbol, exchange, startDt, enddt, interval='1m') cost = (time.process_time() - dt0) print(u'合约%s的分钟K线数据下载完成%s - %s,耗时%s秒' % (symbol, startDt, enddt, cost)) print(jq.get_query_count()) print('-' * 50) print u'合约分钟线数据下载完成' print('-' * 50) return None
def update_data(self) -> None: """""" data = self.engine.get_bar_data_available() total = len(data) count = 0 dialog = QtWidgets.QProgressDialog( "历史数据更新中", "取消", 0, 100 ) dialog.setWindowTitle("更新进度") dialog.setWindowModality(QtCore.Qt.WindowModal) dialog.setValue(0) for d in data: if dialog.wasCanceled(): break self.engine.download_bar_data( d["symbol"], Exchange(d["exchange"]), Interval(d["interval"]), d["end"] ) count += 1 progress = int(round(count / total * 100, 0)) dialog.setValue(progress) dialog.close()
def load_bar_data( self, symbol: str, exchange: Exchange, interval: Interval, start: datetime, end: datetime ) -> List[BarData]: """""" s: ModelSelect = ( DbBarData.select().where( (DbBarData.symbol == symbol) & (DbBarData.exchange == exchange.value) & (DbBarData.interval == interval.value) & (DbBarData.datetime >= start) & (DbBarData.datetime <= end) ).order_by(DbBarData.datetime) ) vt_symbol = f"{symbol}.{exchange.value}" bars: List[BarData] = [] for db_bar in s: db_bar.datetime = DB_TZ.localize(db_bar.datetime) db_bar.exchange = Exchange(db_bar.exchange) db_bar.interval = Interval(db_bar.interval) db_bar.gateway_name = "DB" db_bar.vt_symbol = vt_symbol bars.append(db_bar) return bars
def load_bar_data(self, symbol: str, exchange: Exchange, interval: Interval, start: datetime, end: datetime) -> List[BarData]: """""" s: ModelSelect = ( DbBarData.select().where((DbBarData.symbol == symbol) & (DbBarData.exchange == exchange.value) & (DbBarData.interval == interval.value) & (DbBarData.datetime >= start) & (DbBarData.datetime <= end)).order_by( DbBarData.datetime)) bars: List[BarData] = [] for db_bar in s: bar = BarData(symbol=db_bar.symbol, exchange=Exchange(db_bar.exchange), datetime=db_bar.datetime.astimezone(DB_TZ), interval=Interval(db_bar.interval), volume=db_bar.volume, turnover=db_bar.turnover, open_interest=db_bar.open_interest, open_price=db_bar.open_price, high_price=db_bar.high_price, low_price=db_bar.low_price, close_price=db_bar.close_price, gateway_name="DB") bars.append(bar) return bars
def save_to_database(data: List[dict], vt_symbol: str, rq_interval: str): interval = INTERVAL_RQ2VT.get(rq_interval) if not rq_interval: return None symbol, exchange = extract_vt_symbol(vt_symbol) exchange = Exchange(exchange) dt_format = "%Y-%m-%d %H:%M:%S" res_list: List[BarData] = [] if data is not None: for row in data: bar = BarData(symbol=symbol, exchange=exchange, interval=interval, datetime=datetime.strptime( row['datetime'], dt_format), open_price=row["open"], high_price=row["high"], low_price=row["low"], close_price=row["close"], volume=row["volume"], gateway_name="RQ_WEB") res_list.append(bar) database_manager.save_bar_data(res_list)
def load_tick_data( self, symbol: str, exchange: Exchange, start: datetime, end: datetime ) -> List[TickData]: """""" s: QuerySet = DbTickData.objects( symbol=symbol, exchange=exchange.value, datetime__gte=convert_tz(start), datetime__lte=convert_tz(end), ) vt_symbol = f"{symbol}.{exchange.value}" ticks: List[TickData] = [] for db_tick in s: db_tick.datetime = DB_TZ.localize(db_tick.datetime) db_tick.exchange = Exchange(db_tick.exchange) db_tick.gateway_name = "DB" db_tick.vt_symbol = vt_symbol ticks.append(db_tick) return ticks
def load_bar_data( self, symbol: str, exchange: Exchange, interval: Interval, start: datetime, end: datetime ) -> List[BarData]: """""" s: QuerySet = DbBarData.objects( symbol=symbol, exchange=exchange.value, interval=interval.value, datetime__gte=convert_tz(start), datetime__lte=convert_tz(end), ) vt_symbol = f"{symbol}.{exchange.value}" bars: List[BarData] = [] for db_bar in s: db_bar.datetime = DB_TZ.localize(db_bar.datetime) db_bar.exchange = Exchange(db_bar.exchange) db_bar.interval = Interval(db_bar.interval) db_bar.gateway_name = "DB" db_bar.vt_symbol = vt_symbol bars.append(db_bar) return bars
def set_parameters(self, vt_symbol: str, interval: Interval, start: datetime, rate: float, slippage: float, size: float, pricetick: float, capital: int = 0, end: datetime = None, mode: BacktestingMode = BacktestingMode.BAR, inverse: bool = False): """""" self.mode = mode self.vt_symbol = vt_symbol self.interval = Interval(interval) self.rate = rate self.slippage = slippage self.size = size self.pricetick = pricetick self.start = start self.symbol, exchange_str = self.vt_symbol.split(".") self.exchange = Exchange(exchange_str) self.capital = capital self.end = end self.mode = mode self.inverse = inverse # 更新日志目录 self.logs_path = os.path.abspath( os.path.join(os.getcwd(), 'log', self.test_name))
def to_investment(self): investment = InvestmentData( id=self.id, exchange=Exchange(self.exchange), product_code=self.product_code, symbol=self.symbol, open_price=self.open_price, finish_price=self.finish_price, volume=self.volume, close_volume=self.close_volume, direction=Direction(self.direction), money_lock=self.money_lock, profit=self.profit, profit_rate=self.profit_rate, net_profit=self.net_profit, cost_fee=self.cost_fee, strategy=self.strategy, start_datetime=self.start_datetime, end_datetime=self.end_datetime, open_trade_id=self.open_trade_id, close_trade_ids=self.close_trade_ids.split(",") if self.close_trade_ids is not None else None, state=InvestmentState(self.state), engine_type=EngineType(self.engine_type)) return investment
def load_tick_data( self, symbol: str, exchange: Exchange, start: datetime, end: datetime ) -> List[TickData]: """""" s: QuerySet = DbTickData.objects( symbol=symbol, exchange=exchange.value, datetime__gte=convert_tz(start), datetime__lte=convert_tz(end), ) ticks: List[TickData] = [] for db_tick in s: tick = TickData( symbol=db_tick.symbol, exchange=Exchange(db_tick.exchange), datetime=db_tick.datetime.astimezone(DB_TZ), name=db_tick.name, volume=db_tick.volume, turnover=db_tick.turnover, open_interest=db_tick.open_interest, last_price=db_tick.last_price, last_volume=db_tick.last_volume, limit_up=db_tick.limit_up, limit_down=db_tick.limit_down, open_price=db_tick.open_price, high_price=db_tick.high_price, low_price=db_tick.low_price, pre_close=db_tick.pre_close, bid_price_1=db_tick.bid_price_1, bid_price_2=db_tick.bid_price_2, bid_price_3=db_tick.bid_price_3, bid_price_4=db_tick.bid_price_4, bid_price_5=db_tick.bid_price_5, ask_price_1=db_tick.ask_price_1, ask_price_2=db_tick.ask_price_2, ask_price_3=db_tick.ask_price_3, ask_price_4=db_tick.ask_price_4, ask_price_5=db_tick.ask_price_5, bid_volume_1=db_tick.bid_volume_1, bid_volume_2=db_tick.bid_volume_2, bid_volume_3=db_tick.bid_volume_3, bid_volume_4=db_tick.bid_volume_4, bid_volume_5=db_tick.bid_volume_5, ask_volume_1=db_tick.ask_volume_1, ask_volume_2=db_tick.ask_volume_2, ask_volume_3=db_tick.ask_volume_3, ask_volume_4=db_tick.ask_volume_4, ask_volume_5=db_tick.ask_volume_5, localtime=db_tick.localtime, gateway_name="DB" ) ticks.append(tick) return ticks