炒股看均线能挣钱吗
先说说常见的均线指标:ma5和ma10,学名是五日价格移动平均线和十日价格移动平均线,简称5日线和10日线。大部分人对这两个均线很熟,但是它们的实际作用,众说纷纭,褒贬各异。具体怎么样,我利用backtrader进行验证。
backtrader是python开发的一个回测框架,简单易用,是国外一个牛人开发的,文档也是英文的,本次做一个简单的量化策略回测。
先来看看这个简单的量化策略:
ma5上穿ma10买入,ma10下穿ma5卖出。
做出这个策略的买入卖出理由很简单:5日线上穿10日线,股价处于强势;10日线下穿5日线,股价处于弱势。明白这个后,接下来就是编写代码了。
第一步,安装backtrader。
pip install backtrader
第二步,准备数据。
我已经利用之前的开源代码提前下载了数据,以股票代码为名的csv文件。
后复权的数据
每个csv文件包含日期,开盘价,收盘价,最高价,最低价,成交量。
第三步,编写代码。
首先编写自己的策略类,引入backtrader,继承里面的策略类。这个地方我给自己的策略命名为MyStrategy,并且定义两个变量分别代表需要的均线,比如5日均线和10日均线。
import backtrader as btclass MyStrategy(bt.Strategy): # 均线参数,5日和10日 params = ( ('ma_1', 5), ('ma_2', 10), ) def stop(self): print("结束了")
backtrader自带了指标计算的公式,因此我们只需要调用即可,根据策略,我们应该要计算5日均线和10日均线,继续在策略类里面编写,代码实现起来很简单。backtrader真的很优秀。
def __init__(self): self.dataclose = self.datas[0].close self.order = None self.buyprice = None self.buycomm = None # 五日移动平均线 self.sma5 = bt.indicators.SimpleMovingAverage(period=self.params.ma_1) # 十日移动平均线 self.sma10 = bt.indicators.SimpleMovingAverage(period=self.params.ma_2)
接下来实现买入卖出。按照策略,翻译成通俗语言是:一,如果没有仓位,当天ma5大于ma10,并且前一天ma5小于ma10买入;二,如果当前持仓,那么当ma10大于ma5时就卖出。
backtrader给我们提供了对应的接口方法(notify_order、notify_trade、next),我们只需要编写成这个策略的代码即可。明白这个后,代码应该这样编写:
def notify_order(self, order): if order.status in [order.Submitted, order.Accepted]: # 如订单已被处理,则不用做任何事情 return # 检查订单是否完成 if order.status in [order.Completed]: if order.isbuy(): self.log( '执行买入,买入价格: %.2f, 花费资金: %.2f, 手续费: %.2f' % (order.executed.price, order.executed.value, order.executed.comm)) self.buyprice = order.executed.price self.buycomm = order.executed.comm else: # 卖出 self.log('执行卖出, 卖出价格: %.2f, 花费资金: %.2f, 手续费: %.2f' % (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('本次操作利润, 总计: %.2f, 净利润: %.2f' % (trade.pnl, trade.pnlcomm)) def next(self): # self.log('收盘, %.2f' % self.dataclose[0]) # 检查是否正在准备下单,如果是则直接返回 if self.order: return # 检查是否持仓 if not self.position: # 没有仓位,执行买入条件判断: if self.sma5[0] > self.sma10[0] and self.sma5[-1] < self.sma10[-1]: self.log('买入, %.2f' % self.dataclose[0]) self.log('当前ma5:%.2f, 当前ma10: %.2f, 前一日ma5:%.2f, 前一日ma10: %.2f' % (self.sma5[0], self.sma10[0], self.sma5[-1], self.sma10[-1])) # 买入 self.order = self.buy() else: # 执行条件卖出 if self.sma5[0] < self.sma10[0]: self.log('卖出, %.2f' % self.dataclose[0]) # 卖出 self.order = self.sell()
上面的代码里面都有注释,阅读起来应该没有难度。顺便说一下,如果你们也编写代码,最好也多写点注释,方便自己后面阅读。有的人可能不信邪,半个月或者半年后,这个代码也许就没人看得懂了[泪奔]。相信黄sir,保持这个习惯,你会收获更多的尊重和成就。
策略类已经编写完了,下一步是把csv的文件数据加载进去运行。backtrader提供了很多加载的接口,非常方便,这里我用的是加载pandas数据接口。当然也可以直接传文件路径进去,因为我的csv文件里面有很多其他的数据,因此读取后进行修改只加载基础的数据即可。
import pandas as pd df = pd.read_csv("000001.csv") new_df = df[["日期", "开盘", "收盘", "最高", "最低", "成交量"]] new_df.columns = ["trade_date", "open", "close", "high", "low", "volume"] new_df["trade_date"] = pd.to_datetime(new_df["trade_date"]) new_df.set_index("trade_date", inplace=True) new_df['openinterest'] = 0 cerebro = bt.Cerebro() # 加载我们的策略 cerebro.addstrategy(MyStrategy) # 从2010-01-01到2021-12-17的数据进行回测 data = bt.feeds.PandasData( dataname=new_df, fromdate=datetime.datetime(2010, 1, 1), todate=datetime.datetime(2021, 12, 17) ) cerebro.adddata(data)
接下来设置初始金额和手续费。
# 初始资金 init_amount = 300000.0 cerebro.broker.setcash(init_amount) # 设置每笔交易交易的股票数量 cerebro.addsizer(bt.sizers.FixedSize, stake=100) # 手续费 cerebro.broker.setcommission(commission=0.0)
最后,运行策略。
# 运行策略 cerebro.run() # 结果 result_amount = cerebro.broker.getvalue() print('初始资金: %.2f' % init_amount) print('期末资金: %.2f' % result_amount) print('盈利: %.2f' % (float(result_amount) - init_amount))
一切顺利,结果如下:
可以看到,对于000001,0手续费的情况下11年时间亏损了1176元。
当然,一个股票说明不了什么,换成茅台(600519)试试。
茅台回测结果
总算看到好的结果了,盈利了。如果改动一下指标,比如5日均线换成3日均线,10日均线换成12日均线,结果如何呢?
3日均线和12日均线000001回测结果
3日均线和12日均线600519回测结果
可以看到,亏损减少了,盈利增加了。说明啥?常用的指标赚钱越来越难!通俗点讲:大家都知道的,就是很难赚钱。和股票总数朝市场最小阻力方向运行异曲同工。
当然可以对全市场的股票进行回测,我们把相关代码封装成一个函数,每次把股票代码传进去,然后把结果存起来,感兴趣的朋友可以先自己试试,如果你们想看结果,可以评论留言,想看的人多,下期我再发出来。
另外,黄sir拉了一个群,如果对量化投资感兴趣可以私信我。备注,黄sir很帅,[做鬼脸]
好了,本期的测试就完成了,如果希望看到更多关于量化方面的内容,记得加一个关注,以免迷路。