晶羽科技-解读点评影视小说作品

微信
手机版

炒股看均线能挣钱吗

2022-01-13 00:20 作者:黄sir量化交易之路 围观:

先说说常见的均线指标: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很帅,[做鬼脸]

好了,本期的测试就完成了,如果希望看到更多关于量化方面的内容,记得加一个关注,以免迷路。

相关文章