实现《深入Python:双均线量化交易策略实战》

        双均线策略是比较经典的策略,股票的价格均线是投资参考的重要指标。均线有快线和慢线之分,当快线向上穿过慢线则是金叉,一般执行买入操作,当快线向下穿过慢线时则形成死叉,一般执行卖出操作。基于这个基本思路,出于兴趣爱好,便使用python复现了这个量化策略。代码封装如下。

        在运行这个代码块时,请先运行以下代码:

        pip install pandas

        pip install numpy

        pip install matplotlib

        pip install tqdm

        pip install qstock

        在电脑上安装了这些库之后就可以运行下面的封装代码了,具体讲解在代码块下面。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from tqdm import tqdm
import qstock as qs

class Dual_moving_average_stra():
    '''
    code --> '000001'  str
    start_time --> '20220101'  str
    window0 --> 5  int
    window1 --> 10  int
    verbose --> bool  default=True
    plot --> bool default=True
    init_money = 10000 一万块本金 看末期能有多少收益
    '''
    def __init__(self, code, start_time, window0, window1, verbose=True, plot=True):
        self.code = code
        self.start_time = start_time
        self.window0 = window0
        self.window1 = window1
        self.verbose = verbose
        self.plot = plot
        
    def get_data(self):
        #print(self.code, self.start_time)
        df = qs.get_data(self.code, start=self.start_time, end=None, freq=101, fqt=1)
        df['MA_' + str(self.window0)] = df.rolling(self.window0, min_periods=1).mean()['close'] 
        df['MA_' + str(self.window1)] = df.rolling(self.window1, min_periods=1).mean()['close'] 
        df['gold'] = np.nan
        df.gold = df['MA_' + str(self.window0)] > df['MA_' + str(self.window1)]
        signal = pd.DataFrame()
        signal = df.gold.apply(lambda x:1 if x==True else 0)
        df['gold_death_cha'] = signal - signal.shift(1).fillna(0)
        return df
    
    def strategy(self):
        init_money = 10000
        quant = 0
        df = self.get_data()
        signal = df.gold_death_cha
        price_list = df.open
        money_list = []
        
        for i in tqdm(range(df.shape[0])):
            if i+1 == df.shape[0]: # 因为是次日买卖 所以得提前一天结束代码
                break

            price = price_list.iloc[i+1]

            if signal.iloc[i] == 1: 
                # 金叉全仓买入
                quant += int(init_money / (price * 100))
                init_money -= quant * price * 100
                if self.verbose == True:
                    print('此次购买数量:', quant)
                    print('证券价格:', price)
                    print('本金还剩:',init_money)
                    print('金叉买入执行完毕----------------------------------')

            if signal.iloc[i] == -1:
                init_money += quant * price * 100
                quant = 0 # 清仓
                money_list.append(init_money)
                if self.verbose == True:
                    print('清仓:', quant)
                    print('证券价格:', price)
                    print('本金还剩:',init_money)
                    print('死叉卖出执行完毕----------------------------------')
        
        if self.plot == True:
            plt.figure(figsize=(20,20))
            plt.subplot(2,1,1)
            plt.grid()
            plt.plot(df.index, df.close, label='close', linewidth=3)
            plt.plot(df.index, df['MA_' + str(self.window0)], c='red', label=('MA_' + str(self.window0)), linewidth=3)
            plt.plot(df.index, df['MA_' + str(self.window1)], c='grey', label=('MA_' + str(self.window1)), linewidth=3)
            plt.xticks(rotation=45)
            plt.legend(fontsize=20)
            
            plt.subplot(2,1,2)
            plt.grid()
            plt.plot(range(len(money_list)), money_list, linewidth=3, label='money')
            plt.xticks(rotation=45)
            plt.legend(fontsize=20)
            plt.show()

        这是一个金叉死叉的策略,在股价出现死叉时则全仓卖出,在股价出现金叉时则全仓买入,然后给予10000元的本金,查看最后一期能剩余多少本金。

        首先实例化我们的对象:

model = Dual_moving_average_stra('600460', '20200101', 5, 20)

        第一个参数是股票代码,第二个参数是提取数据的开始时间,例子中是从2020年开始的。5表示计算股票的5日均线,20表示计算股票的20日均线。然后就完成了模型的实例化。

model.strategy()

        然后再运行这个代码就可以查看策略的效果了。

此次购买数量: 6
证券价格: 16.52
本金还剩: 88.0
金叉买入执行完毕----------------------------------
清仓: 0
证券价格: 13.63
本金还剩: 8266.0
死叉卖出执行完毕----------------------------------
此次购买数量: 4
证券价格: 18.67
本金还剩: 797.9999999999991
金叉买入执行完毕----------------------------------
清仓: 0
证券价格: 17.74
本金还剩: 7893.999999999998
死叉卖出执行完毕----------------------------------
此次购买数量: 5
证券价格: 14.7
本金还剩: 543.9999999999982
金叉买入执行完毕----------------------------------
清仓: 0
证券价格: 14.26
本金还剩: 7673.999999999998
死叉卖出执行完毕----------------------------------
此次购买数量: 5
证券价格: 14.67
本金还剩: 338.9999999999991
金叉买入执行完毕----------------------------------
清仓: 0
证券价格: 17.23
本金还剩: 8954.0
死叉卖出执行完毕----------------------------------
此次购买数量: 5
证券价格: 16.63
本金还剩: 639.0
金叉买入执行完毕----------------------------------
清仓: 0
证券价格: 16.28
本金还剩: 8779.0
死叉卖出执行完毕----------------------------------
此次购买数量: 5
证券价格: 15.78
本金还剩: 889.0000000000009
金叉买入执行完毕----------------------------------
清仓: 0
证券价格: 25.62
本金还剩: 13699.0
死叉卖出执行完毕----------------------------------
此次购买数量: 5
证券价格: 27.09
本金还剩: 154.00000000000182
金叉买入执行完毕----------------------------------
清仓: 0
证券价格: 25.66
本金还剩: 12984.000000000004
死叉卖出执行完毕----------------------------------
此次购买数量: 4
证券价格: 26.12
本金还剩: 2536.0000000000036
金叉买入执行完毕----------------------------------
清仓: 0
证券价格: 24.28
本金还剩: 12248.000000000004
死叉卖出执行完毕----------------------------------
此次购买数量: 4
证券价格: 30.48
本金还剩: 56.00000000000364
金叉买入执行完毕----------------------------------
清仓: 0
证券价格: 57.4
本金还剩: 23016.000000000004
死叉卖出执行完毕----------------------------------
此次购买数量: 3
证券价格: 63.35
本金还剩: 4011.0000000000036
金叉买入执行完毕----------------------------------
清仓: 0
证券价格: 61.9
本金还剩: 22581.000000000004
死叉卖出执行完毕----------------------------------
此次购买数量: 3
证券价格: 57.57
本金还剩: 5310.000000000004
金叉买入执行完毕----------------------------------
清仓: 0
证券价格: 53.4
本金还剩: 21330.0
死叉卖出执行完毕----------------------------------
此次购买数量: 3
证券价格: 61.11
本金还剩: 2997.0
金叉买入执行完毕----------------------------------
清仓: 0
证券价格: 54.7
本金还剩: 19407.000000000004
死叉卖出执行完毕----------------------------------
此次购买数量: 3
证券价格: 63.39
本金还剩: 390.00000000000364
金叉买入执行完毕----------------------------------
清仓: 0
证券价格: 65.1
本金还剩: 19920.000000000004
死叉卖出执行完毕----------------------------------
此次购买数量: 3
证券价格: 61.64
本金还剩: 1428.0000000000036
金叉买入执行完毕----------------------------------
清仓: 0
证券价格: 59.26
本金还剩: 19206.000000000004
死叉卖出执行完毕----------------------------------
此次购买数量: 3
证券价格: 51.92
本金还剩: 3630.0000000000036
金叉买入执行完毕----------------------------------
清仓: 0
证券价格: 50.55
本金还剩: 18795.0
死叉卖出执行完毕----------------------------------
此次购买数量: 3
证券价格: 55.29
本金还剩: 2208.0
金叉买入执行完毕----------------------------------
清仓: 0
证券价格: 54.35
本金还剩: 18513.0
死叉卖出执行完毕----------------------------------
此次购买数量: 4
证券价格: 42.49
本金还剩: 1517.0
金叉买入执行完毕----------------------------------
清仓: 0
证券价格: 45.58
本金还剩: 19749.0
死叉卖出执行完毕----------------------------------
此次购买数量: 4
证券价格: 46.08
本金还剩: 1317.0
金叉买入执行完毕----------------------------------
清仓: 0
证券价格: 45.45
本金还剩: 19497.0
死叉卖出执行完毕----------------------------------
此次购买数量: 3
证券价格: 50.79
本金还剩: 4260.0
金叉买入执行完毕----------------------------------
清仓: 0
证券价格: 46.77
本金还剩: 18291.0
。。。

        模型可以打印每次买入和卖出的日志,模型中的参数 verbose 和plot是默认打开的,可以看需求关闭。同时Plot参数提供了可视化, 上方的图表示股价图,下方图则是本金变化图形。

        从图形可以看出600460的股价从20年的低点到21年的高年翻了将近6倍,而均线策略最高只取得了两倍的收益。

        我们可以继续换一组参数,用5日线和10日线来操作。

model = Dual_moving_average_stra('600460', '20200101', 5, 10)
model.strategy()

         可以看出来效果会比5日线和20日线的组合好一点。个人感觉这个策略比较依赖标的。

物联沃分享整理
物联沃-IOTWORD物联网 » 实现《深入Python:双均线量化交易策略实战》

发表评论