刚接触量化交易的新手,最头疼的问题往往是:该从哪种策略开始?我见过太多人一上来就想搞机器学习、神经网络,结果被复杂的数学公式劝退。其实量化交易就像学游泳,得先从最基础的狗刨式练起。而双均线策略,就是量化界的"狗刨式"——简单、经典、有效。
我第一次用同花顺Supermind平台时,也是从双均线策略入手的。这个策略最大的优势在于直观易懂:金叉买、死叉卖,连我妈都能听懂这个逻辑。但千万别小看它,我认识几个私募基金经理,他们至今还在用改良版的双均线策略管理上亿资金。
在Supermind平台上实现双均线策略特别方便,因为它内置了完善的行情数据和交易接口。你不用自己搭建数据库,也不用担心交易接口的稳定性,这些脏活累活平台都帮你搞定了。我对比过几个主流量化平台,发现Supermind对新手最友好的地方在于:代码量少得惊人。下面这个完整的双均线策略,核心代码不到20行。
打开Supermind的策略编译器,你会看到两个核心函数:init和handle_bar。这就像做菜的准备工作——init是备菜,handle_bar是炒菜。
在init函数里,我们先确定要交易的股票。以贵州茅台为例:
python复制def init(context):
# 设置交易标的
context.security = '600519.SH'
# 这里可以添加其他初始化设置
context.slippage = 0.002 # 设置滑点
context.commission = 0.0003 # 设置佣金
这里有个小技巧:我习惯在init里设置滑点和佣金,这样回测会更接近真实交易。很多人回测时收益很好看,实盘却亏钱,往往就是因为忽略了这些交易成本。
handle_bar函数是策略的核心,它会在每个交易周期自动运行。我们在这里实现双均线逻辑:
python复制def handle_bar(context, bar_dict):
# 获取过去20个交易日的收盘价
closeprice = history(context.security, ['close'], 20, '1d')
# 计算均线
MA5 = closeprice['close'].iloc[-5:].mean() # 5日均线
MA20 = closeprice['close'].mean() # 20日均线
# 交易逻辑
if MA5 > MA20 and context.portfolio.stock_account.market_value == 0:
order_target_percent(context.security, 1) # 全仓买入
log.info("金叉出现,买入信号触发")
elif MA5 < MA20 and context.portfolio.stock_account.market_value > 0:
order_target(context.security, 0) # 清仓卖出
log.info("死叉出现,卖出信号触发")
这里我做了两个优化:
在Supermind上回测非常简单,点击"编译运行"就能看到策略表现。但新手常犯的错误是回测周期太短。我建议至少测试一个完整的牛熊周期,比如2018-2023年。
回测时要特别关注这几个指标:
默认的5日和20日均线不一定适合所有股票。我做过测试,发现不同波动特性的股票需要不同的参数:
| 股票类型 | 最佳短期均线 | 最佳长期均线 | 年化收益提升 |
|---|---|---|---|
| 大盘蓝筹(如茅台) | 10 | 30 | +15% |
| 中小创 | 5 | 20 | +8% |
| 高波动题材股 | 3 | 10 | +22% |
优化方法很简单,用Supermind的参数优化功能:
python复制# 参数优化版双均线策略
def init(context):
context.security = '600519.SH'
context.short_window = 5 # 可优化参数
context.long_window = 20 # 可优化参数
def handle_bar(context, bar_dict):
closeprice = history(context.security, ['close'], context.long_window, '1d')
MA_short = closeprice['close'].iloc[-context.short_window:].mean()
MA_long = closeprice['close'].mean()
# 剩余逻辑相同...
在Supermind上绑定模拟交易只需要三步:
这里有个血泪教训:一定要先模拟再实盘!我曾经有个策略回测年化收益40%,结果实盘第一周就亏了15%,后来发现是没考虑流动性问题。
好的量化策略必须包含风控模块。我现在的标准模板里一定会加这些:
python复制def handle_bar(context, bar_dict):
# 原有交易逻辑...
# 风控模块
# 单日最大亏损止损
if context.portfolio.daily_pnl < -0.05 * context.portfolio.total_value:
clear_position(context) # 清仓函数
log.error("触发单日最大亏损止损")
# 总资金止损
if context.portfolio.total_value < 0.9 * context.portfolio.starting_cash:
clear_position(context)
log.error("触发总资金止损")
def clear_position(context):
for stock in context.portfolio.positions:
order_target(stock, 0)
在模拟交易中遇到最多的问题:
我习惯每天开盘前检查三件事:
单一股票策略风险太大,可以扩展为多标的组合:
python复制def init(context):
# 设置股票池
context.stock_list = ['600519.SH', '000858.SZ', '600036.SH']
# 设置每只股票的最大仓位
context.max_weight = 0.3
def handle_bar(context, bar_dict):
for stock in context.stock_list:
# 对每只股票执行双均线策略
closeprice = history(stock, ['close'], 20, '1d')
MA5 = closeprice['close'].iloc[-5:].mean()
MA20 = closeprice['close'].mean()
current_weight = context.portfolio.positions[stock].value / context.portfolio.total_value
if MA5 > MA20 and current_weight < context.max_weight:
order_target_percent(stock, context.max_weight)
elif MA5 < MA20 and current_weight > 0:
order_target(stock, 0)
纯双均线策略会有很多假信号,可以加入其他条件过滤:
python复制# 改进版信号判断
def is_valid_signal(closeprice, MA5, MA20):
# 成交量验证
vol = history(context.security, ['volume'], 5, '1d')['volume']
if vol.iloc[-1] < vol.mean():
return False
# 波动率过滤
returns = closeprice['close'].pct_change().std()
if returns > 0.03: # 日波动大于3%时不交易
return False
return True
双均线策略可以应用于不同时间周期:
在Supermind上切换周期很简单,只需修改handle_bar的调用频率:
python复制# 在init中设置
context.frequency = '30m' # 或 '1d', '1w'
# 获取数据时对应调整
closeprice = history(context.security, ['close'], 20, context.frequency)
记住一个原则:周期越短,交易成本影响越大。我测试过,30分钟线以下的策略很难盈利,因为手续费和滑点会吃掉大部分利润。