增加交易策略、交易指标、量化库代码等文件夹
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from update_etf_data import *"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"合约信息更新成功 642\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"contracts = update_contract_data(\"上证期权\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"ContractData(gateway_name='XT', extra=None, symbol='10005765', exchange=<Exchange.SSE: 'SSE'>, name='50ETF购3月2411A', product=<Product.OPTION: '期权'>, size=10161, pricetick=0.0001, min_volume=1, stop_supported=False, net_position=False, history_data=False, option_strike=2.411, option_underlying='510050-2403', option_type=<OptionType.CALL: '看涨期权'>, option_listed=datetime.datetime(2023, 7, 27, 0, 0), option_expiry=datetime.datetime(2024, 3, 27, 0, 0), option_portfolio='510050', option_index='2.411')\n",
|
||||
"ContractData(gateway_name='XT', extra=None, symbol='10006712', exchange=<Exchange.SSE: 'SSE'>, name='300ETF沽6月3700', product=<Product.OPTION: '期权'>, size=10000, pricetick=0.0001, min_volume=1, stop_supported=False, net_position=False, history_data=False, option_strike=3.7, option_underlying='510300-2406', option_type=<OptionType.PUT: '看跌期权'>, option_listed=datetime.datetime(2024, 1, 19, 0, 0), option_expiry=datetime.datetime(2024, 6, 26, 0, 0), option_portfolio='510300', option_index='3.7')\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print(contracts[0])\n",
|
||||
"print(contracts[-1])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"update_bar_data()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.9"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from update_rqdata_data import *"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"合约信息更新成功 4808\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"contracts = update_contract_data(Exchange.CFFEX)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"ContractData(gateway_name='RQ', extra=None, symbol='HO2301-C-2325', exchange=<Exchange.CFFEX: 'CFFEX'>, name='HO2301-C-2325', product=<Product.OPTION: '期权'>, size=100.0, pricetick=0.2, min_volume=1.0, stop_supported=False, net_position=False, history_data=False, option_strike=2325.0, option_underlying='HO2301', option_type=<OptionType.CALL: '看涨期权'>, option_listed=datetime.datetime(2022, 12, 21, 0, 0), option_expiry=datetime.datetime(2023, 1, 20, 0, 0), option_portfolio='HO', option_index='2325.0')\n",
|
||||
"ContractData(gateway_name='RQ', extra=None, symbol='MO2412-P-6600', exchange=<Exchange.CFFEX: 'CFFEX'>, name='MO2412-P-6600', product=<Product.OPTION: '期权'>, size=100.0, pricetick=0.2, min_volume=1.0, stop_supported=False, net_position=False, history_data=False, option_strike=6600.0, option_underlying='MO2412', option_type=<OptionType.PUT: '看跌期权'>, option_listed=datetime.datetime(2023, 12, 18, 0, 0), option_expiry=datetime.datetime(2024, 12, 20, 0, 0), option_portfolio='MO', option_index='6600.0')\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print(contracts[0])\n",
|
||||
"print(contracts[-1])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"update_bar_data()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.9"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
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(".")
|
||||
|
||||
# 筛选期权合约合约(ETF期权代码为8位)
|
||||
if len(symbol) == 8:
|
||||
data: dict = get_instrument_detail(xt_symbol, True)
|
||||
#print(data)
|
||||
#raise Exception("fuck")
|
||||
name: str = data["InstrumentName"]
|
||||
if "购" in name:
|
||||
option_type = OptionType.CALL
|
||||
elif "沽" in name:
|
||||
option_type = OptionType.PUT
|
||||
else:
|
||||
continue
|
||||
|
||||
# 获取期权组合
|
||||
option_portfolio = data["ExtendInfo"]["OptUndlCode"]
|
||||
|
||||
# 获取期权链(标的)
|
||||
option_expiry = datetime.strptime(data["ExpireDate"], "%Y%m%d")
|
||||
option_underlying = option_portfolio + "-" + option_expiry.strftime("%y%m")
|
||||
|
||||
# 生成合约对象
|
||||
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_portfolio=option_portfolio,
|
||||
option_underlying=option_underlying,
|
||||
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))
|
||||
|
||||
return 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_contract_data("深证期权")
|
||||
update_contract_data("过期深证期权")
|
||||
|
||||
# 更新历史数据
|
||||
update_bar_data()
|
||||
@@ -0,0 +1,163 @@
|
||||
from datetime import datetime
|
||||
|
||||
import rqdatac
|
||||
import pandas as pd
|
||||
|
||||
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 elite_database import EliteDatabase
|
||||
|
||||
|
||||
# 初始化数据服务
|
||||
datafeed = get_datafeed()
|
||||
datafeed.init()
|
||||
|
||||
|
||||
# 交易所映射关系
|
||||
EXCHANGE_RQ2VT = {
|
||||
"XSHG": Exchange.SSE,
|
||||
"XSHE": Exchange.SZSE,
|
||||
"SHFE": Exchange.SHFE,
|
||||
"CFFEX": Exchange.CFFEX,
|
||||
"INE": Exchange.INE,
|
||||
"DCE": Exchange.DCE,
|
||||
"CZCE": Exchange.CZCE,
|
||||
"GFEX": Exchange.GFEX
|
||||
}
|
||||
|
||||
|
||||
def update_contract_data(exchange: Exchange) -> None:
|
||||
"""更新合约数据"""
|
||||
# 查询期权信息
|
||||
df: pd.DataFrame = rqdatac.all_instruments(type="Option")
|
||||
|
||||
# 转换合约对象
|
||||
contracts: list[ContractData] = []
|
||||
|
||||
for tp in df.itertuples():
|
||||
# 交易所过滤
|
||||
if exchange != EXCHANGE_RQ2VT[tp.exchange]:
|
||||
continue
|
||||
|
||||
# 确认期权类型
|
||||
if tp.option_type == "C":
|
||||
option_type = OptionType.CALL
|
||||
else:
|
||||
option_type = OptionType.PUT
|
||||
|
||||
# 获取最小价格变动
|
||||
pricetick: float = rqdatac.instruments(tp.order_book_id).tick_size()
|
||||
|
||||
# 获取期权链(标的)
|
||||
if "-" in tp.trading_code:
|
||||
option_underlying = tp.trading_code.split("-")[0]
|
||||
else:
|
||||
suffix = tp.trading_code.replace(tp.underlying_symbol, "")
|
||||
ix = suffix.index(tp.option_type)
|
||||
time_str = suffix[:ix]
|
||||
option_underlying = tp.underlying_symbol + time_str
|
||||
|
||||
# 创建期权对象
|
||||
contract = ContractData(
|
||||
symbol=tp.trading_code,
|
||||
exchange=exchange,
|
||||
name=tp.trading_code,
|
||||
product=Product.OPTION,
|
||||
size=tp.contract_multiplier,
|
||||
pricetick=pricetick,
|
||||
min_volume=tp.round_lot,
|
||||
option_strike=tp.strike_price,
|
||||
option_listed=datetime.strptime(tp.listed_date, "%Y-%m-%d"),
|
||||
option_expiry=datetime.strptime(tp.maturity_date, "%Y-%m-%d"),
|
||||
option_portfolio=tp.underlying_symbol,
|
||||
option_index=str(tp.strike_price),
|
||||
option_underlying=option_underlying,
|
||||
option_type=option_type,
|
||||
gateway_name="RQ"
|
||||
)
|
||||
|
||||
contracts.append(contract)
|
||||
|
||||
# 保存合约信息到数据库
|
||||
database: EliteDatabase = EliteDatabase()
|
||||
database.save_contract_data(contracts)
|
||||
|
||||
print("合约信息更新成功", len(contracts))
|
||||
|
||||
return 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__":
|
||||
# 更新合约信息
|
||||
update_contract_data(Exchange.CFFEX)
|
||||
|
||||
# 更新历史数据
|
||||
update_bar_data()
|
||||
Reference in New Issue
Block a user