量化交易之均值回复策略


import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
# import seaborn as sns
# % matplotlib inline
# sns.set_context(rc={'figure.figsize': (14, 7) } )
# figzize_me = figsize =(14, 7)
# import warnings;
# warnings.filterwarnings('ignore')

# import os
# import sys
# sys.path.append(os.path.abspath('../'))
from cmd.finance import GetData

data = GetData.get_data('../data/002236.csv')
# 选定使用特斯拉两年的股票走势数据
# 头一年([:252])作为训练数据, 美股交易中一年的交易日有252天
train_kl = data[-100:-50]
# 后一年([252:])作为回测数据
test_kl = data[-50:]
buy_signal=0
sell_signal=0

# def shape():
#     sns.set_context(rc={'figure.figsize': (14, 7)})
#     sns.regplot(x=np.arange(0, data.shape[0]), y=data.close.values, marker='+')
#     plt.show()
def train_plot():
    # 分别画出两部分数据收盘价格曲线
    tmp_df = pd.DataFrame(
        np.array([train_kl.close.values, test_kl.close.values]).T,
        columns=['train', 'test'])

    tmp_df[['train', 'test']].plot(subplots=True, grid=True,
                                   figsize=(14, 7));
    plt.show()
def train_run():
    global buy_signal,sell_signal
    # 训练数据的收盘价格均值
    close_mean = train_kl.close.mean()
    # 训练数据的收盘价格标准差
    close_std = train_kl.close.std()

    # 构造卖出信号阀值
    sell_signal = close_mean + close_std / 3
    # 构造买入信号阀值
    buy_signal = close_mean - close_std / 3
    # sell_signal=13.8
    # buy_signal=11.8
    # 可视化训练数据的卖出信号阀值,买入信号阀值及均值线
    plt.figure(figsize=(14, 7))
    # 训练集收盘价格可视化
    train_kl.close.plot()
    # 水平线,买入信号线, lw代表线的粗度
    plt.axhline(buy_signal, color='r', lw=3)
    # 水平线,均值线
    plt.axhline(close_mean, color='black', lw=1)
    # 水平线, 卖出信号线
    plt.axhline(sell_signal, color='g', lw=3)
    plt.legend(['train close', 'buy_signal', 'close_mean', 'sell_signal'],
               loc='best')
    # plt.show()

    # 将卖出信号阀值,买入信号阀值代入回归测试数据可视化
    plt.figure(figsize=(14, 7))
    # 测试集收盘价格可视化
    test_kl.close.plot()
    # buy_signal直接代入买入信号
    plt.axhline(buy_signal, color='r', lw=3)
    # 直接代入训练集均值close
    plt.axhline(close_mean, color='black', lw=1)
    # sell_signal直接代入卖出信号
    plt.axhline(sell_signal, color='g', lw=3)
    # 按照上述绘制顺序标注
    plt.legend(['test close', 'buy_signal', 'close_mean', 'sell_signal'],
               loc='best')
    # plt.show()
    
    print('买入信号阀值:{} 卖出信号阀值:{}'.format(buy_signal, sell_signal))
def test_buy():
    global buy_signal, sell_signal
    # 寻找测试数据中满足买入条件的时间序列
    buy_index = test_kl[test_kl['close'] <= buy_signal].index

    # 将找到的买入时间系列的信号设置为1,代表买入操作
    test_kl.loc[buy_index, 'signal'] = 1
    # 表7-2所示
    print(test_kl[52:57])

    # 寻找测试数据中满足卖出条件的时间序列
    sell_index = test_kl[test_kl['close'] >= sell_signal].index

    # 将找到的卖出时间系列的信号设置为0,代表卖出操作
    test_kl.loc[sell_index, 'signal'] = 0
    # 表7-3所示
    print(test_kl[48:53])

    # 由于假设都是全仓操作所以signal=keep,即1代表买入持有,0代表卖出空仓
    test_kl['keep'] = test_kl['signal']
    # 将keep列中的nan使用向下填充的方式填充,结果使keep可以代表最终的交易持股状态
    test_kl['keep'].fillna(method='ffill', inplace=True)
    # shift(1)及np.log下面会有内容详细讲解
    test_kl['benchmark_profit'] = \
        np.log(test_kl['close'] / test_kl['close'].shift(1))

    # 仅仅为了说明np.log的意义,添加了benchmark_profit2,只为对比数据是否一致
    test_kl['benchmark_profit2'] = \
        test_kl['close'] / test_kl['close'].shift(1) - 1

    # 可视化对比两种方式计算出的profit是一致的
    test_kl[['benchmark_profit', 'benchmark_profit2']].plot(subplots=True,
                                                            grid=True,
                                                            figsize=(
                                                                14, 7));
    # plt.show()

    test_kl['trend_profit'] = test_kl['keep'] * test_kl['benchmark_profit']
    test_kl['trend_profit'].plot(figsize=(14, 7))
    # plt.show()

    test_kl[['benchmark_profit', 'trend_profit']].cumsum().apply(
    np.exp).plot(grid=True);
    plt.show()
if __name__=='__main__':
    # shape()
    # train_plot()
    train_run()
    test_buy()


猜你喜欢

转载自blog.csdn.net/luansj/article/details/105342079
今日推荐