使用ctpplus,然后增加回测模块
This commit is contained in:
+85
-37
@@ -7,6 +7,7 @@ import threading # 线程模块
|
||||
import os # 操作系统模块
|
||||
import json # JSON模块
|
||||
import re # 正则表达式模块
|
||||
import csv # CSV模块
|
||||
import time as time_module # 标准库时间模块
|
||||
from datetime import datetime, time as datetime_time # datetime时间对象
|
||||
from multiprocessing import Process, Queue # 多进程模块
|
||||
@@ -167,12 +168,23 @@ class OrderFlowTrader(TraderApiBase):
|
||||
# 数据存储
|
||||
self._json_save_counter = {} # JSON保存计数器
|
||||
self.md_queue = md_queue # 行情队列
|
||||
self._tick_record_counter = {} # tick录制计数器 {symbol: count}
|
||||
|
||||
# ============ 行情数据处理 ============
|
||||
|
||||
def tickcome(self, md_queue):
|
||||
"""接收并处理Tick行情数据"""
|
||||
data = md_queue # 从队列获取行情数据
|
||||
|
||||
# === tick录制(实盘模式) ===
|
||||
if SYSTEM_CONFIG.get("record_tick", False):
|
||||
instrument_id_raw = data["InstrumentID"]
|
||||
symbol = instrument_id_raw.decode() if isinstance(instrument_id_raw, bytes) else instrument_id_raw
|
||||
self._tick_record_counter[symbol] = self._tick_record_counter.get(symbol, 0) + 1
|
||||
interval = SYSTEM_CONFIG.get("tick_record_interval", 1)
|
||||
if self._tick_record_counter[symbol] % interval == 0:
|
||||
self._record_tick_to_csv(data, symbol)
|
||||
|
||||
instrument_id = data["InstrumentID"].decode() # 解码合约代码
|
||||
action_day = data["ActionDay"].decode() # 解码交易日期
|
||||
update_time = data["UpdateTime"].decode() # 解码更新时间
|
||||
@@ -215,6 +227,36 @@ class OrderFlowTrader(TraderApiBase):
|
||||
}
|
||||
self.on_tick(tick) # 调用Tick处理回调
|
||||
|
||||
def _record_tick_to_csv(self, data: dict, symbol: str):
|
||||
"""录制 tick 数据到 CSV"""
|
||||
data_dir = SYSTEM_CONFIG["data_dir"]
|
||||
os.makedirs(data_dir, exist_ok=True)
|
||||
csv_path = f"{data_dir}/{symbol}_tick.csv"
|
||||
|
||||
# CSV 字段
|
||||
fields = [
|
||||
"InstrumentID", "ActionDay", "UpdateTime", "UpdateMillisec",
|
||||
"LastPrice", "Volume", "BidPrice1", "BidVolume1",
|
||||
"AskPrice1", "AskVolume1", "UpperLimitPrice", "LowerLimitPrice",
|
||||
"TradingDay", "Turnover", "OpenInterest"
|
||||
]
|
||||
|
||||
# 写入字段(bytes 解码)
|
||||
row = {}
|
||||
for field in fields:
|
||||
val = data.get(field)
|
||||
if isinstance(val, bytes):
|
||||
row[field] = val.decode()
|
||||
else:
|
||||
row[field] = val
|
||||
|
||||
file_exists = os.path.exists(csv_path)
|
||||
with open(csv_path, 'a', newline='', encoding='utf-8') as f:
|
||||
writer = csv.DictWriter(f, fieldnames=fields)
|
||||
if not file_exists:
|
||||
writer.writeheader()
|
||||
writer.writerow(row)
|
||||
|
||||
def on_tick(self, tick):
|
||||
"""处理单个Tick数据"""
|
||||
if tick["last_volume"] == 0: # 无成交量则返回
|
||||
@@ -330,6 +372,8 @@ class OrderFlowTrader(TraderApiBase):
|
||||
of = DataStore.ofdata.pop(symbol, None)
|
||||
if of is not None:
|
||||
self.data_of(symbol, of) # 写入交易DataFrame
|
||||
# 保存 ofdata.json(改善时间戳对齐:旧K线完成时即保存)
|
||||
self.save_ofdata_json(symbol)
|
||||
|
||||
# 清空旧K线的报价数据
|
||||
with self._quote_lock:
|
||||
@@ -1033,9 +1077,6 @@ class OrderFlowTrader(TraderApiBase):
|
||||
# 计算Delta累计(必须在保存之前)
|
||||
self.calculate_delta_cumulative(trade_df, param)
|
||||
|
||||
# 保存 ofdata.json(计算 delta累计 之后)
|
||||
self.save_ofdata_json(instrument_id)
|
||||
|
||||
# 计算交易信号
|
||||
bull_signal, bear_signal, dj_last, delta_last = self.calculate_signals(trade_df, param)
|
||||
|
||||
@@ -1146,44 +1187,51 @@ if __name__ == "__main__":
|
||||
for symbol, config in TRADING_PARAMS.items():
|
||||
param_dict[symbol] = TradingParam.from_config(symbol, config)
|
||||
|
||||
# 连接SimNow模拟交易
|
||||
future_account = get_simulate_account(
|
||||
investor_id=SIMNOW_CONFIG["investor_id"],
|
||||
password=SIMNOW_CONFIG["password"],
|
||||
server_name=SIMNOW_CONFIG["server_name"],
|
||||
subscribe_list=list(param_dict.keys()),
|
||||
)
|
||||
# ===模式切换:回测模式 ===
|
||||
if SYSTEM_CONFIG.get("mode", "live") == "backtest":
|
||||
from backtest import Backtester
|
||||
backtester = Backtester(param_dict)
|
||||
backtester.run()
|
||||
else:
|
||||
# === 实盘/模拟模式 ===
|
||||
# 连接SimNow模拟交易
|
||||
future_account = get_simulate_account(
|
||||
investor_id=SIMNOW_CONFIG["investor_id"],
|
||||
password=SIMNOW_CONFIG["password"],
|
||||
server_name=SIMNOW_CONFIG["server_name"],
|
||||
subscribe_list=list(param_dict.keys()),
|
||||
)
|
||||
|
||||
# 连接实盘(备用)
|
||||
# from CtpPlus.CTP.FutureAccount import FutureAccount
|
||||
# future_account = FutureAccount(...)
|
||||
# 连接实盘(备用)
|
||||
# from CtpPlus.CTP.FutureAccount import FutureAccount
|
||||
# future_account = FutureAccount(...)
|
||||
|
||||
print("开始", len(future_account.subscribe_list))
|
||||
print("开始", len(future_account.subscribe_list))
|
||||
|
||||
# 创建共享队列
|
||||
share_queue = Queue(maxsize=SYSTEM_CONFIG["queue_share_size"])
|
||||
# 创建共享队列
|
||||
share_queue = Queue(maxsize=SYSTEM_CONFIG["queue_share_size"])
|
||||
|
||||
# 启动行情进程
|
||||
md_process = Process(target=run_tick_engine, args=(future_account, [share_queue]))
|
||||
# 启动行情进程
|
||||
md_process = Process(target=run_tick_engine, args=(future_account, [share_queue]))
|
||||
|
||||
# 启动交易进程
|
||||
trader_process = Process(
|
||||
target=run_trader,
|
||||
args=(
|
||||
param_dict,
|
||||
future_account.broker_id,
|
||||
future_account.server_dict["TDServer"],
|
||||
future_account.investor_id,
|
||||
future_account.password,
|
||||
future_account.app_id,
|
||||
future_account.auth_code,
|
||||
share_queue,
|
||||
future_account.td_flow_path,
|
||||
),
|
||||
)
|
||||
# 启动交易进程
|
||||
trader_process = Process(
|
||||
target=run_trader,
|
||||
args=(
|
||||
param_dict,
|
||||
future_account.broker_id,
|
||||
future_account.server_dict["TDServer"],
|
||||
future_account.investor_id,
|
||||
future_account.password,
|
||||
future_account.app_id,
|
||||
future_account.auth_code,
|
||||
share_queue,
|
||||
future_account.td_flow_path,
|
||||
),
|
||||
)
|
||||
|
||||
md_process.start() # 启动行情进程
|
||||
trader_process.start() # 启动交易进程
|
||||
md_process.start() # 启动行情进程
|
||||
trader_process.start() # 启动交易进程
|
||||
|
||||
md_process.join() # 等待行情进程结束
|
||||
trader_process.join() # 等待交易进程结束
|
||||
md_process.join() # 等待行情进程结束
|
||||
trader_process.join() # 等待交易进程结束
|
||||
Reference in New Issue
Block a user