保姆级教程:用Hikyuu框架从零搭建你的第一个量化策略(附完整代码)

张开发
2026/5/30 12:31:31 15 分钟阅读
保姆级教程:用Hikyuu框架从零搭建你的第一个量化策略(附完整代码)
从零构建Hikyuu量化策略双均线实战全流程解析写在前面第一次接触量化交易时我被那些复杂的数学公式和专业术语吓得不轻。直到发现Hikyuu这个框架才真正体会到用代码实现交易想法的乐趣。今天要分享的这个双均线策略是我三年前入门的第一个策略虽然简单但包含了量化系统最核心的要素。通过这个案例你不仅能快速上手Hikyuu还能掌握量化策略开发的标准流程。1. 环境准备与数据导入1.1 安装Hikyuu的正确姿势别急着pip install先准备好这些# 创建专属的量化环境避免包冲突 python -m venv hikyuu_env source hikyuu_env/bin/activate # Linux/Mac hikyuu_env\Scripts\activate # Windows现在安装Hikyuu核心包pip install hikyuu -i https://pypi.tuna.tsinghua.edu.cn/simple注意如果安装时报错缺少C编译环境需要先安装Visual Studio Build ToolsWindows或Xcode Command Line ToolsMac1.2 数据准备实战Hikyuu需要本地化的K线数据这里推荐两种获取方式数据源优点缺点Tushare Pro数据全面更新及时需要注册和积分Baostock完全免费接口稍复杂本地CSV完全自主可控需要自己维护更新以Tushare为例获取平安银行(000001.SZ)日线数据import tushare as ts pro ts.pro_api(你的token) df pro.daily(ts_code000001.SZ, start_date20190101, end_date20231231) df.to_csv(000001.SZ.csv, indexFalse)1.3 数据导入Hikyuu系统Hikyuu使用HDF5格式存储数据转换命令如下hikyuu_load --type day --market sz --code 000001 --file 000001.SZ.csv --dir ./hikyuu_data关键配置文件hikyuu.ini示例[market] sz_day_dir ./hikyuu_data sh_day_dir ./hikyuu_data [database] type sqlite path ./hikyuu_data/base_info.db初始化StockManager的Python代码from hikyuu import hikyuu_init, StockManager hikyuu_init() # 自动加载当前目录下的hikyuu.ini sm StockManager.instance() print(f已加载股票数量{len(sm.stock_list)})2. 双均线策略核心实现2.1 策略逻辑拆解这个经典策略包含三个关键信号买入信号短期均线上穿长期均线金叉卖出信号短期均线下穿长期均线死叉过滤条件收盘价在长期均线之上趋势确认策略参数配置建议参数类型默认值优化范围说明短期均线周期105-20反映短期价格趋势长期均线周期3020-60反映中长期价格趋势过滤比例0%0%-5%避免假突破的缓冲区间2.2 代码完整实现from hikyuu import * from hikyuu.indicator import MA, CROSS # 初始化K线查询 stock sm.get_stock(sz000001) query KQueryByDate(start_dateDatetime(201901010000), end_dateDatetime(202312310000), ktypeQuery.DAY, recover_typeQuery.FORWARD) kdata stock.get_kdata(query) # 计算技术指标 close kdata.close ma_short MA(close, 10) # 10日均线 ma_long MA(close, 30) # 30日均线 # 构建交易信号 buy_signal CROSS(ma_short, ma_long) # 金叉 sell_signal CROSS(ma_long, ma_short) # 死叉 # 配置交易系统 system SYS_Simple( sgSG_Single(buy_signal, sell_signal), mmMM_FixedPercent(0.2), # 每次使用20%资金 tmTradeManager() ) system.trade_manager.init_cash 100000 # 初始资金10万 system.name DualMA_Strategy # 运行回测 system.run(kdata)2.3 关键组件解析Hikyuu的策略系统由多个模块组成Signal信号产生买卖信号SG_Single单一信号触发SG_Cross交叉信号专用SG_Flex灵活组合信号MoneyManager资金管理# 固定数量模式 MM_FixedCount(1000) # 每次交易1000股 # 固定比例模式 MM_FixedPercent(0.3) # 每次使用30%资金 # 固定风险模式 MM_FixedRisk(1000) # 每次最大亏损1000元TradeManager交易管理记录所有交易明细计算账户资产变动生成绩效指标3. 回测结果深度分析3.1 基础绩效指标运行完回测后可以提取这些关键指标tm system.trade_manager stats tm.statistics performance { 初始资金: tm.init_cash, 期末总资产: tm.current_cash tm.get_stock_value(kdata.stock, kdata[-1].close), 总收益率: stats[profit] / tm.init_cash, 年化收益率: stats[annualized_returns], 最大回撤: stats[max_drawdown], 胜率: stats[win_rate], 夏普比率: stats[sharpe_ratio], 交易次数: stats[total_trades] }3.2 可视化分析用Matplotlib绘制资金曲线和买卖点import matplotlib.pyplot as plt # 资金曲线 funds_curve tm.get_funds_curve(kdata) plt.figure(figsize(12, 6)) plt.plot(funds_curve.get_datetime_list(), funds_curve.get_value_list(), label资金曲线) # 标记买卖点 trade_records tm.trade_list for trade in trade_records: if trade.business BUSINESS_BUY: plt.scatter(trade.datetime, funds_curve.get_value(trade.datetime), colorred, marker^, label买入) else: plt.scatter(trade.datetime, funds_curve.get_value(trade.datetime), colorgreen, markerv, label卖出) plt.title(策略资金曲线与交易信号) plt.legend() plt.show()3.3 参数敏感性测试测试不同均线组合的表现from itertools import product short_periods [5, 10, 15] long_periods [20, 30, 50] results [] for s, l in product(short_periods, long_periods): if s l: continue system.reset() system.sg SG_Single(CROSS(MA(close, s), MA(close, l)), CROSS(MA(close, l), MA(close, s))) system.run(kdata) stats system.trade_manager.statistics results.append({ short: s, long: l, annual_return: stats[annualized_returns], max_drawdown: stats[max_drawdown] }) # 转换为DataFrame分析 import pandas as pd df_results pd.DataFrame(results) print(df_results.sort_values(annual_return, ascendingFalse).head())4. 策略优化与进阶技巧4.1 常见优化方向参数优化网格搜索法遗传算法贝叶斯优化信号增强# 增加成交量过滤 vol_ma MA(kdata.volume, 20) buy_signal (CROSS(ma_short, ma_long)) (kdata.volume vol_ma) # 增加波动率过滤 atr ATR(kdata, 14) buy_signal buy_signal (atr atr.ref(1))风险控制# 加入止损策略 system.st ST_FixedPercent(0.05) # 5%止损 # 动态仓位调整 def dynamic_mm(system, kdata): risk 1 - system.trade_manager.statistics[max_drawdown] return min(0.3, 0.1 * risk) # 根据回撤动态调整仓位4.2 实盘衔接要点数据对接设置定时任务自动更新数据实现实时行情订阅接口交易执行# 伪代码示例 def execute_order(signal, price, amount): if signal buy: broker.buy(price, amount) else: broker.sell(price, amount) # 在System的after_signal方法中调用监控体系异常交易检测滑点监控策略健康度检查4.3 性能提升技巧向量化计算# 不好的写法 for i in range(len(kdata)): ma_short[i] sum(close[i-9:i1])/10 # 好的写法 ma_short MA(close, 10) # 使用内置向量化计算并行回测from concurrent.futures import ProcessPoolExecutor def backtest(params): short, long params # ...回测逻辑... return results with ProcessPoolExecutor() as executor: results list(executor.map(backtest, param_combinations))缓存机制from functools import lru_cache lru_cache(maxsize100) def get_kdata(stock_code, query): return sm.get_stock(stock_code).get_kdata(query)5. 从策略到产品化5.1 策略封装模式将策略打包成可配置组件class DualMAStrategy: def __init__(self, short10, long30, risk0.2): self.params { short: Parameter(short, 5, 20, 1), long: Parameter(long, 20, 60, 5), risk: Parameter(risk, 0.1, 0.5, 0.05) } def build_system(self): return SYS_Simple( sgSG_Single(self._buy_signal(), self._sell_signal()), mmMM_FixedPercent(self.params[risk].value), namefDualMA_{self.params[short].value}_{self.params[long].value} ) def _buy_signal(self): # 信号生成逻辑 pass5.2 自动化运维方案建议的运维架构[数据采集模块] - [策略引擎] - [风险控制模块] ↓ ↓ ↓ [数据库] [信号分发中心] [报警系统] ↓ ↓ [监控面板] [交易执行]关键组件实现示例class StrategyEngine: def __init__(self): self.strategies {} self.data_feeds {} def add_strategy(self, name, strategy): self.strategies[name] strategy def run(self): while True: self._update_data() self._generate_signals() self._risk_check() time.sleep(60) # 每分钟运行一次 def _update_data(self): # 数据更新逻辑 pass5.3 常见问题解决方案问题1回测结果很好但实盘亏损解决方案检查是否有未来函数增加交易成本测算测试不同市场环境问题2策略突然失效处理流程立即停止交易检查数据质量回测近期表现分析市场结构变化问题3执行延迟严重优化方向改用VPS就近部署优化代码执行效率与券商API直连写在最后三年前用这个双均线策略跑出第一条盈利曲线时的兴奋感至今难忘。虽然现在看起来这个策略很简单但它教会我最重要的一课量化交易的核心不是寻找圣杯策略而是建立可重复、可验证的交易逻辑。建议新手在修改参数前先完整走通这个基础策略的全流程理解每个模块的输入输出这比直接套用复杂策略要有价值得多。

更多文章