学习《深入浅出python量化交易交易实战》第二章(笔记2)

上一篇我们实现了本书中的简策略的回测:学习《深入浅出python量化交易交易实战》第二章(笔记1)

本片文章是本书第二章平移策略的相关内容

1.学习《深入浅出python量化交易交易实战》第二章(笔记2)

记录学习过程中的代码、疑问和心得

2. 经典策略----移动平均策略 Single Moving Average, SMA

2.1 单一移动平均指数

移动平均策略的核心思想非常简单,且十分容易理解:

  • 当股价上升且向上穿过N日的均线时,说明股价在向上突破,此时下单买入;
    当股价下降且乡下穿过N日均线时,说明股价整体出现下跌趋势,此时卖出;

  • 或当M日均价上升穿过N日的均线时(M<N),说明股票处于上升趋势,应下单买入;
    反之,当M日均价格下降且穿过N日均线时,说明股票处于下降趋势,应卖出。

下面是单一平均策略的代码实现:

import pandas as pd
import numpy as np
from chapter_2_get import gen_stock_data_table 
import matplotlib.pyplot as plt

stock_data = gen_stock_data_table('002419', '20220101', '20221231')
stock_002419 = stock_data['stock']
# 使用10日均线
period = 10

# 设置一个空表,用来存储每10天的价格
avg_10 = []

# 设置一个空列表,用来存储每10天价格的均值
avg_value = []

# 设置一个循环
for price in stock_002419['close']:
    # 每天的价格传入avg_10
    avg_10.append(price)
    # 当列表中存储的数多余10个
    if len(avg_10) > period:
        # 就把前面传入的价格数据删除,确保列表中最多只有10天的数据
        del avg_10[0]
    # 将计算好的每个10日均价写入股票价格数据表中
    # np.mean() 求平均值
    avg_value.append(np.mean(avg_10))
# pd.Series创建一维数组,index 为stock_002419的index
# stock_002419.assign() 增加一个列
stock_002419_avg = stock_002419.assign(
    avg_10=pd.Series(avg_value, index=stock_002419.index)
)
print('avg:', stock_002419_avg)


# 可视化

plt.figure(figsize=(10, 6))
# 绘制股价变化
plt.plot(stock_002419_avg['close'],  '-', lw=2, c='r', label='price')

# 绘制10日均线
plt.plot(stock_002419_avg['avg_10'], '--', lw=2, c='b', label='avg_10')

# 添加图注和网格
# plt.legend()
plt.grid()
plt.show()

在这里插入图片描述

2.2 双移动平均策略

顾名思义,双移动平均策略就是使用两条均线来判断股价未来的走势。
两条均线中,一条是长均线(如10日均线),另一条是短均线(如5日均线)。

这种策略基于一种假设:股价的动量回朝着短期均线的方向移动。当短期均线超过长期移动均线时,
动量向上,此时股价可能会上涨。然而,如果短期均线的移动方向相反,则股价可能下跌。

策略的代码实现:
chapter_2_2_DMA.py


import pandas as pd
import numpy as np
from chapter_2_get import gen_stock_data_table


# 双移动平均策略的封装
def gen_dma_strategy_data(symbol, start_date, end_date):
    stock_data = gen_stock_data_table(symbol, start_date, end_date)
    stock_002419 = stock_data['stock']
    # 新建一个数据表 strategy
    # 序号和原始数据保持一致
    strategy = pd.DataFrame(index=stock_002419.index)
    # signal,用来存储交易信号 卖出:0, 买入:1
    strategy['price'] = stock_002419['close']
    strategy['signal'] = 0

    # 将5日均线保存到avg_5,10日均线保存到avg_10
    # dataframe.rolling()函数提供滚动窗口计算的功能
    strategy['avg_5'] = stock_002419['close'].rolling(5).mean()
    strategy['avg_10'] = stock_002419['close'].rolling(10).mean()

    # 当5日均价大于10日均价时,标记为1---买入
    # 反之,标记为0---卖出
    strategy['signal'] = np.where(strategy['avg_5'] > strategy['avg_10'], 1, 0)

    # 根据信号的变化下单,当信号为0-->1时买入
    # 当信号从1-->0时卖出
    # 交易信号不变时不下单
    strategy['order'] = strategy['signal'].diff()
    order_cn_map = {
        -1.0: '卖出',
        0.0: '持有',
        1.0: '买入',
    }
    strategy['order_cn'] = strategy['order'].map(order_cn_map)
    # strategy = strategy.fillna('--')
    return strategy

回测:

	
	from chapter_2_2_DMA import gen_dma_strategy_data
import matplotlib.pyplot as plt
import pandas as pd

dma_strategy_data = gen_dma_strategy_data('002419', '20220101', '20221231')

print(dma_strategy_data)

'''
strategy_data: 策略的数据
initial_cash: 初始资金
'''

def draw_dma_stock_cash(data):
    plt.figure(figsize=(10, 6))
    plt.plot(data['stock_value'], lw=2, label='stock_value')
    plt.plot(data['total'], lw=2, ls='--', label='total')
    plt.legend()
    plt.grid()
    plt.show()

# 绘图 价格、5日均线和10日均线
def draw_dma_chart(data):
    # 绘制
    plt.figure(figsize=(50, 12))
    # 绘制股价变化
    plt.plot(data['price'], lw=1, c='y', label="price")
    plt.plot(data['avg_5'], ls='--', c='r', lw=2, label="avg5")
    plt.plot(data['avg_10'], ls='-.', c='b', lw=2, label="avg10")

    # 买入卖出信号标记
    plt.scatter(
        data.loc[data.order == 1].index,
        data['price'][data.order == 1],
        marker='^', s=50, color='r', label='buy'
    )
    plt.scatter(
        data.loc[data.order == -1].index,
        data['price'][data.order == -1],
        marker='v', s=50, color='g', label='sell'
    )

    plt.legend()
    plt.grid()
    plt.show()

draw_dma_chart(dma_strategy_data)

# 回测
def test(strategy_data, initial_cash):
    print('============test DMA===============')
    # 新建一个positions表,序号和strategy数据表保持一致
    positions = pd.DataFrame(index=strategy_data.index).fillna(0)
    print(positions)

    # 因为A股都是最低100股
    # 因此设置stock字段为交易信号的100倍
    positions['stock'] = strategy_data['signal'] * 100
    portfolio = pd.DataFrame(index=positions.index)
    portfolio['stock_value'] = positions.multiply(strategy_data['price'], axis=0)
    # 仓位变价就是下单的数量
    order = positions.diff()
    print('交易量')
    print(order.tail(20))
    portfolio['stock'] = positions['stock']
    # 初始资金减去下单金额的总和就是剩余的资金
    portfolio['cash'] = initial_cash - order.multiply(strategy_data['price'], axis=0).cumsum()
    portfolio['total'] = portfolio['cash'] + portfolio['stock_value']
    print(portfolio.tail(10))
    draw_dma_stock_cash(portfolio)


test(dma_strategy_data, 20000)



双移动平均策略回测结果输出:
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝with黑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值