from multiprocessing import Process from datetime import datetime from vnpy.trader.database import BarOverview from vnpy.trader.datafeed import get_datafeed from vnpy.trader.object import ContractData, BarData, HistoryRequest from vnpy.trader.constant import Exchange, Product, OptionType, Interval from vnpy.trader.setting import SETTINGS from elite_database import EliteDatabase # 配置迅投研数据服务 SETTINGS["datafeed.name"] = "xt" SETTINGS["datafeed.username"] = "token" SETTINGS["datafeed.password"] = "" # 交易所映射关系 EXCHANGE_XT2VT = { "SH": Exchange.SSE, "SZ": Exchange.SZSE, "BJ": Exchange.BSE, "SF": Exchange.SHFE, "IF": Exchange.CFFEX, "INE": Exchange.INE, "DF": Exchange.DCE, "ZF": Exchange.CZCE, "GF": Exchange.GFEX } def update_history_data() -> None: """更新历史合约信息""" # 在子进程中加载xtquant from xtquant.xtdata import download_history_data # 初始化数据服务 datafeed = get_datafeed() datafeed.init() # 下载历史合约信息 download_history_data("", "historycontract") print("xtquant历史合约信息下载完成") def update_contract_data(sector_name: str) -> None: """更新合约数据""" # 在子进程中加载xtquant from xtquant.xtdata import ( get_stock_list_in_sector, get_instrument_detail ) # 初始化数据服务 datafeed = get_datafeed() datafeed.init() # 查询中金所历史合约代码 vt_symbols: list[str] = get_stock_list_in_sector(sector_name) # 遍历列表查询合约信息 contracts: list[ContractData] = [] for xt_symbol in vt_symbols: # 拆分XT代码 symbol, xt_exchange = xt_symbol.split(".") # 筛选期权合约合约 if "-" in symbol: data: dict = get_instrument_detail(xt_symbol, True) type_str = data["InstrumentID"].split("-")[1] if type_str == "C": option_type = OptionType.CALL elif type_str == "P": option_type = OptionType.PUT option_underlying: str = data["InstrumentID"].split("-")[0] contract: ContractData = ContractData( symbol=data["InstrumentID"], exchange=EXCHANGE_XT2VT[xt_exchange.replace("O", "")], name=data["InstrumentName"], product=Product.OPTION, size=data["VolumeMultiple"], pricetick=data["PriceTick"], min_volume=data["MinLimitOrderVolume"], option_strike=data["ExtendInfo"]["OptExercisePrice"], option_listed=datetime.strptime(data["OpenDate"], "%Y%m%d"), option_expiry=datetime.strptime(data["ExpireDate"], "%Y%m%d"), option_underlying=option_underlying, option_portfolio=data["ProductID"], option_index=str(data["ExtendInfo"]["OptExercisePrice"]), option_type=option_type, gateway_name="XT" ) contracts.append(contract) # 保存合约信息到数据库 database: EliteDatabase = EliteDatabase() database.save_contract_data(contracts) print("合约信息更新成功", len(contracts)) def update_bar_data() -> None: """更新K线数据""" # 初始化数据服务 datafeed = get_datafeed() datafeed.init() # 获取当前时间戳 now: datetime = datetime.now() # 获取合约信息 database: EliteDatabase = EliteDatabase() contracts: list[ContractData] = database.load_contract_data() # 获取数据汇总 data: list[BarOverview] = database.get_bar_overview() overviews: dict[str, BarOverview] = {} for o in data: # 只保留分钟线数据 if o.interval != Interval.MINUTE: continue vt_symbol: str = f"{o.symbol}.{o.exchange.value}" overviews[vt_symbol] = o # 遍历所有合约信息 for contract in contracts: # 如果没有到期时间,则跳过 if not contract.option_expiry: continue # 查询数据汇总 overview: BarOverview = overviews.get(contract.vt_symbol, None) # 如果已经到期,则跳过 if overview and contract.option_expiry < now: continue # 初始化查询开始的时间 start: datetime = datetime(2018, 1, 1) # 实现增量查询 if overview: start = overview.end # 执行数据查询和更新入库 req: HistoryRequest = HistoryRequest( symbol=contract.symbol, exchange=contract.exchange, start=start, end=datetime.now(), interval=Interval.MINUTE ) bars: list[BarData] = datafeed.query_bar_history(req) if bars: database.save_bar_data(bars) start_dt: datetime = bars[0].datetime end_dt: datetime = bars[-1].datetime msg: str = f"{contract.vt_symbol}数据更新成功,{start_dt} - {end_dt}" print(msg) if __name__ == "__main__": # 使用子进程更新历史合约信息 process: Process = Process(target=update_history_data) process.start() process.join() # 等待子进程执行完成 # 更新合约信息 update_contract_data("中金所") update_contract_data("过期中金所") # 更新历史数据 # update_bar_data()