年化11.3%,经典海龟系统择时沪深300指数(代码+数据)

海龟是一个经典的交易系统: 

有出入仓信号,有仓位管理原则,有止损。

在沪深300上的运行效果,赢盈指数肯定是没有问题。

图片

import sys

sys.path.append('../')
from matplotlib import rcParams
rcParams['font.family'] = 'SimHei'import backtrader as btfrom datafeed.dataloader import CSVDataloaderclass TurtleStrategy(bt.Strategy): # 默认参数 params = (('long_period', 20), ('short_period', 10), ('printlog', False),) def __init__(self): self.order = None self.buyprice = 0 self.buycomm = 0 self.buy_size = 0 self.buy_count = 0 # 海龟交易法则中的唐奇安通道和平均波幅ATR self.H_line = bt.indicators.Highest(self.data.high(-1), period=self.p.long_period) self.L_line = bt.indicators.Lowest(self.data.low(-1), period=self.p.short_period) self.TR = bt.indicators.Max((self.data.high(0) - self.data.low(0)), \ abs(self.data.close(-1) - self.data.high(0)), \ abs(self.data.close(-1) - self.data.low(0))) self.ATR = bt.indicators.SimpleMovingAverage(self.TR, period=14) # 价格与上下轨线的交叉 self.buy_signal = bt.ind.CrossOver(self.data.close(0), self.H_line) self.sell_signal = bt.ind.CrossOver(self.data.close(0), self.L_line) def next(self): if self.order: return # 入场:价格突破上轨线且空仓时 if self.buy_signal > 0 and self.buy_count == 0: atr = self.ATR[0] self.buy_size = self.broker.getvalue() * 0.01 / self.ATR self.buy_size = int(self.buy_size / 100) * 100 self.sizer.p.stake = self.buy_size # 指定买卖多少股。 print('ATR', atr, 'buy_size', self.sizer.p.stake, 'close', self.data.close[0], '市值', self.broker.getvalue() * 0.01) self.buy_count = 1 # print('空仓时买入', self.buy_size) self.order = self.buy() # 加仓:价格上涨了买入价的0.5ATR且加仓次数少于3次(含) elif self.data.close > self.buyprice + 0.5 * self.ATR[0] and 0 < self.buy_count <= 4: # print('加仓买入') self.buy_size = self.broker.getvalue() * 0.01 / self.ATR self.buy_size = int(self.buy_size / 100) * 100 self.sizer.p.stake = self.buy_size self.order = self.buy() self.buy_count += 1 # 离场:价格跌破下轨线且持仓时 elif self.sell_signal < 0 and self.buy_count > 0: # print('平仓信号卖出') self.order = self.sell() self.buy_count = 0 # 止损:价格跌破买入价的2ATR且持仓时 elif self.data.close < (self.buyprice - 2 * self.ATR[0]) and self.buy_count > 0: # print('止损信号卖出') self.order = self.sell() self.buy_count = 0 # 交易记录日志(默认不打印结果) def log(self, txt, dt=None, doprint=False): if self.params.printlog or doprint: dt = dt or self.datas[0].datetime.date(0) print(f'{dt.isoformat()},{txt}') # 记录交易执行情况(默认不输出结果) def notify_order(self, order): # 如果ordersubmitted/accepted,返回空 if order.status in [order.Submitted, order.Accepted]: return # 如果orderbuy/sell executed,报告价格结果 if order.status in [order.Completed]: if order.isbuy(): self.log(f'买入:\n价格:{order.executed.price},\ 成本:{order.executed.value},\ 手续费:{order.executed.comm}') self.buyprice = order.executed.price self.buycomm = order.executed.comm else: self.log(f'卖出:\n价格:{order.executed.price},\ 成本: {order.executed.value},\ 手续费{order.executed.comm}') self.bar_executed = len(self) # 如果指令取消/交易失败, 报告结果 elif order.status in [order.Canceled, order.Margin, order.Rejected]: self.log('交易失败') self.order = None # 记录交易收益情况(可省略,默认不输出结果) def notify_trade(self, trade): if not trade.isclosed: return self.log(f'策略收益:\n毛收益 {trade.pnl:.2f}, 净收益 {trade.pnlcomm:.2f}') def stop(self): self.log(f'(组合线:{self.p.long_period},{self.p.short_period})\ 期末总资金: {self.broker.getvalue():.2f}', doprint=True) ''' strat0 = strats[0] pyfolio = strat0.analyzers.getbyname('pyfolio') returns, positions, transactions, gross_lev = pyfolio.get_pf_items() import empyrical as em em.annual_return(returns) transactions '''class TradeSizer(bt.Sizer): params = (('stake', 1),) def _getsizing(self, comminfo, cash, data, isbuy): if isbuy: return self.p.stake position = self.broker.getposition(data) if not position.size: return 0 else: return position.size return self.p.stakedef main(symbol, long_list, short_list, start, end, startcash=1000000, com=0.001): # 创建主控制器 cerebro = bt.Cerebro() cerebro.addstrategy(TurtleStrategy) # 导入策略参数寻优 # cerebro.optstrategy(TurtleStrategy, long_period=long_list, short_period=short_list) # 获取数据 df = CSVDataloader.get_backtrader_df(symbol, start_date=start, end_date=end) data = bt.feeds.PandasData(dataname=df) cerebro.adddata(data) # broker设置资金、手续费 cerebro.broker.setcash(startcash) cerebro.broker.setcommission(commission=com) cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='sharpe_ratio') cerebro.addanalyzer(bt.analyzers.PyFolio, _name='pyfolio') # 设置买入设置,策略,数量 cerebro.addsizer(TradeSizer) print('期初总资金: %.2f' % cerebro.broker.getvalue()) optimized_runs = cerebro.run(maxcpus=1) cerebro.plot()long_list = range(20, 70, 5)short_list = range(5, 20, 5)main('000300.SH', long_list, short_list, '20050101', '20240709')

交易系统

交易系统在金融市场中扮演着至关重要的角色,其重要性可以从以下几个方面来理解:

1、自动化交易:交易系统可以自动执行交易策略,减少人为干预,降低情绪对交易决策的影响。交易系统确保交易策略的一致性执行,避免因个人情绪波动或判断失误导致的不一致性。

2、风控通过预设的规则和参数,交易系统有助于控制交易风险,例如通过止损和止盈来限制潜在的损失。

3、可扩展性:随着市场和技术的发展,交易系统可以不断更新和扩展,以适应新的交易环境和策略。

4、24/7 交易对于全球市场,交易系统可以实现全天候交易,不受交易者工作时间的限制。

量化新手讨论更多的是策略、因子,但忽略了系统的重要性。甚至应该反过来。——我们的目标是:本金安全,然后赚取长久的、稳健的收益。

这与做资产配置、价值投资是不一样的。

资产配置本身就是选择长生不死的指数ETF,长期向上的,这时候,市场回撤就回撤,早晚都会回来。

价值投资也是基于自己的判断,以合适的价格买入基本面良好的资产,市场回调时,反而是建仓的好机会。

说白了,这两者对于回撤没那么敏感,属于左侧交易。

而量化投资(机),尤其以趋势交易,是典型的右侧交易。没有人能预测市场,但市场往预期相反的方向运动时,如何保护好自己,这属于止损和仓位管理的范畴。——这可能不一定属于策略的一部分,而是交易系统的一部分。

一个好的交易系统是,我们要建立这样一个框架,无论市场如何走,亏损有限,而当机会来临时,会有不错的收益。

如此,就可以——以交易为生!

包含本周提及的所有策略:海龟,RSRS,动量,布林带,大类资产配置,风险平价等。

另外,backtrader进行了封装,支持参数优化、多策略运行等

图片

还有人留言cue我说——有本事你搞个私募呀。

其实这是我在想的事情,至少具备一个优秀小型私募的职业投资能力。——以出世的心态,做入世的事情。

至于做不做资管,目前想法可能是不,做自营就好了,没有那么多条条框框,也不想向外界证明什么。

面上几乎能找到的开源框架都用过,多数代码都读过,设计的理念,优缺点——自己也从零写过。

私募策略长什么样子,以交易为生的目标应该是什么样的?

多因子策略容量大,策略比较简单,主要就是“找因子”。——对比传统的规则信号,则是构建指标。——比如前面咱们分享的海龟策略。借由唐奇安通道,使用ATR来加仓或止损。

可以看看一个私募策略的样子:

下面这样的回测+实盘曲线看着就比较舒服——年化收益:33.78%,最大回撤:5.04%。 图片

 这是一家规模3亿左右的私募的短周期截面CTA。

交易标的:交易30+活跃品种,持仓周期:1-3天,价量数据为主,盘前数据参考均来自三方,盘中有自研交易体系做交叉验证,剔除噪音。

因子&迭代:90%截面因子+10%时序因子,均为逻辑因子,单因子较复杂,严控入池条件,原先利用子策略波动率平价系统进行净值波动控制,现利用长周期时序信号调整波动率预期,进而进行择时。

策略模型:多因子打分系统,多前50%空后50%,控市值中性。

几个要点:量价数据为主,但截面多因子轮动,多前空后。截面因子就是横向对比。

先控回测,再谈收益。

如何控制回撤,一是分散,二是仓位,三是止损。

多个标的——相关性越低越好,本身组合在一起就会降低波动(相互对冲——从风控的角度,如公募,单股票不得超过10%也是这个目的,担心过于集中的风险暴露)。多标的一定是截面多因子轮动。

如同我们在大类资产配置里使用的那样。年化达21%(K=1),最大回撤35%,K=3时,卡玛比最优,最大回撤20%(年化15.2%)| Quantlab5.0代码发布

海龟是一个经典的交易系统: 

有出入仓信号,有仓位管理原则,有止损。

在沪深300上的运行效果,赢盈指数肯定是没有问题。

图片

import sys

sys.path.append('../')
from matplotlib import rcParams
rcParams['font.family'] = 'SimHei'import backtrader as btfrom datafeed.dataloader import CSVDataloaderclass TurtleStrategy(bt.Strategy): # 默认参数 params = (('long_period', 20), ('short_period', 10), ('printlog', False),) def __init__(self): self.order = None self.buyprice = 0 self.buycomm = 0 self.buy_size = 0 self.buy_count = 0 # 海龟交易法则中的唐奇安通道和平均波幅ATR self.H_line = bt.indicators.Highest(self.data.high(-1), period=self.p.long_period) self.L_line = bt.indicators.Lowest(self.data.low(-1), period=self.p.short_period) self.TR = bt.indicators.Max((self.data.high(0) - self.data.low(0)), \ abs(self.data.close(-1) - self.data.high(0)), \ abs(self.data.close(-1) - self.data.low(0))) self.ATR = bt.indicators.SimpleMovingAverage(self.TR, period=14) # 价格与上下轨线的交叉 self.buy_signal = bt.ind.CrossOver(self.data.close(0), self.H_line) self.sell_signal = bt.ind.CrossOver(self.data.close(0), self.L_line) def next(self): if self.order: return # 入场:价格突破上轨线且空仓时 if self.buy_signal > 0 and self.buy_count == 0: atr = self.ATR[0] self.buy_size = self.broker.getvalue() * 0.01 / self.ATR self.buy_size = int(self.buy_size / 100) * 100 self.sizer.p.stake = self.buy_size # 指定买卖多少股。 print('ATR', atr, 'buy_size', self.sizer.p.stake, 'close', self.data.close[0], '市值', self.broker.getvalue() * 0.01) self.buy_count = 1 # print('空仓时买入', self.buy_size) self.order = self.buy() # 加仓:价格上涨了买入价的0.5ATR且加仓次数少于3次(含) elif self.data.close > self.buyprice + 0.5 * self.ATR[0] and 0 < self.buy_count <= 4: # print('加仓买入') self.buy_size = self.broker.getvalue() * 0.01 / self.ATR self.buy_size = int(self.buy_size / 100) * 100 self.sizer.p.stake = self.buy_size self.order = self.buy() self.buy_count += 1 # 离场:价格跌破下轨线且持仓时 elif self.sell_signal < 0 and self.buy_count > 0: # print('平仓信号卖出') self.order = self.sell() self.buy_count = 0 # 止损:价格跌破买入价的2ATR且持仓时 elif self.data.close < (self.buyprice - 2 * self.ATR[0]) and self.buy_count > 0: # print('止损信号卖出') self.order = self.sell() self.buy_count = 0 # 交易记录日志(默认不打印结果) def log(self, txt, dt=None, doprint=False): if self.params.printlog or doprint: dt = dt or self.datas[0].datetime.date(0) print(f'{dt.isoformat()},{txt}') # 记录交易执行情况(默认不输出结果) def notify_order(self, order): # 如果ordersubmitted/accepted,返回空 if order.status in [order.Submitted, order.Accepted]: return # 如果orderbuy/sell executed,报告价格结果 if order.status in [order.Completed]: if order.isbuy(): self.log(f'买入:\n价格:{order.executed.price},\ 成本:{order.executed.value},\ 手续费:{order.executed.comm}') self.buyprice = order.executed.price self.buycomm = order.executed.comm else: self.log(f'卖出:\n价格:{order.executed.price},\ 成本: {order.executed.value},\ 手续费{order.executed.comm}') self.bar_executed = len(self) # 如果指令取消/交易失败, 报告结果 elif order.status in [order.Canceled, order.Margin, order.Rejected]: self.log('交易失败') self.order = None # 记录交易收益情况(可省略,默认不输出结果) def notify_trade(self, trade): if not trade.isclosed: return self.log(f'策略收益:\n毛收益 {trade.pnl:.2f}, 净收益 {trade.pnlcomm:.2f}') def stop(self): self.log(f'(组合线:{self.p.long_period},{self.p.short_period})\ 期末总资金: {self.broker.getvalue():.2f}', doprint=True) ''' strat0 = strats[0] pyfolio = strat0.analyzers.getbyname('pyfolio') returns, positions, transactions, gross_lev = pyfolio.get_pf_items() import empyrical as em em.annual_return(returns) transactions '''class TradeSizer(bt.Sizer): params = (('stake', 1),) def _getsizing(self, comminfo, cash, data, isbuy): if isbuy: return self.p.stake position = self.broker.getposition(data) if not position.size: return 0 else: return position.size return self.p.stakedef main(symbol, long_list, short_list, start, end, startcash=1000000, com=0.001): # 创建主控制器 cerebro = bt.Cerebro() cerebro.addstrategy(TurtleStrategy) # 导入策略参数寻优 # cerebro.optstrategy(TurtleStrategy, long_period=long_list, short_period=short_list) # 获取数据 df = CSVDataloader.get_backtrader_df(symbol, start_date=start, end_date=end) data = bt.feeds.PandasData(dataname=df) cerebro.adddata(data) # broker设置资金、手续费 cerebro.broker.setcash(startcash) cerebro.broker.setcommission(commission=com) cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='sharpe_ratio') cerebro.addanalyzer(bt.analyzers.PyFolio, _name='pyfolio') # 设置买入设置,策略,数量 cerebro.addsizer(TradeSizer) print('期初总资金: %.2f' % cerebro.broker.getvalue()) optimized_runs = cerebro.run(maxcpus=1) cerebro.plot()long_list = range(20, 70, 5)short_list = range(5, 20, 5)main('000300.SH', long_list, short_list, '20050101', '20240709')

交易系统

交易系统在金融市场中扮演着至关重要的角色,其重要性可以从以下几个方面来理解:

1、自动化交易:交易系统可以自动执行交易策略,减少人为干预,降低情绪对交易决策的影响。交易系统确保交易策略的一致性执行,避免因个人情绪波动或判断失误导致的不一致性。

2、风控通过预设的规则和参数,交易系统有助于控制交易风险,例如通过止损和止盈来限制潜在的损失。

3、可扩展性:随着市场和技术的发展,交易系统可以不断更新和扩展,以适应新的交易环境和策略。

4、24/7 交易对于全球市场,交易系统可以实现全天候交易,不受交易者工作时间的限制。

量化新手讨论更多的是策略、因子,但忽略了系统的重要性。甚至应该反过来。——我们的目标是:本金安全,然后赚取长久的、稳健的收益。

这与做资产配置、价值投资是不一样的。

资产配置本身就是选择长生不死的指数ETF,长期向上的,这时候,市场回撤就回撤,早晚都会回来。

价值投资也是基于自己的判断,以合适的价格买入基本面良好的资产,市场回调时,反而是建仓的好机会。

说白了,这两者对于回撤没那么敏感,属于左侧交易。

而量化投资(机),尤其以趋势交易,是典型的右侧交易。没有人能预测市场,但市场往预期相反的方向运动时,如何保护好自己,这属于止损和仓位管理的范畴。——这可能不一定属于策略的一部分,而是交易系统的一部分。

一个好的交易系统是,我们要建立这样一个框架,无论市场如何走,亏损有限,而当机会来临时,会有不错的收益。

如此,就可以——以交易为生!

发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/103194
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!

(0)
股市刺客的头像股市刺客
上一篇 2024 年 7 月 26 日
下一篇 2024 年 7 月 26 日

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注