均线策略方法论及其代码实现全解析——(#5天线与10天线金叉且收盘价高于5天线,买入; 5天线与10天线死叉,收盘价低于5天线,卖出)

引言

均线策略在金融市场中占据着重要地位,其广泛应用源于其简单易懂、操作性强的特点。通过计算市场价格的平均值,均线能够平滑价格波动,帮助投资者更好地识别市场趋势,从而做出理性的投资决策。无论是股票市场、期货市场还是外汇市场,均线策略都是投资者不可或缺的工具之一。

均线策略基础知识

        什么是均线

均线,全称为移动平均线(MA),是一种在股票、期货、外汇等金融市场中广泛使用的技术分析工具。它通过对一定时期内的证券价格(如收盘价)进行平均计算,然后将这些平均值连接成一条线,以此反映证券价格在一定时间周期内的变动趋势。均线的主要目的是帮助交易者识别市场的趋势方向,判断市场的支撑和阻力水平,以及捕捉可能的买卖信号。

均线可以分为多种类型,主要依据其计算周期的长短来区分,例如:

  • 短期均线:如5日均线、10日均线等,这类均线对价格变动的反应较为敏感,常用来捕捉市场的短期波动和交易机会。
  • 中期均线:如20日均线、30日均线、60日均线等,这类均线更多地反映市场的中期趋势,对于判断市场的中期方向和支撑/阻力水平有重要意义。
  • 长期均线:如120日均线、250日均线等,这类均线对市场的长期趋势有很好的指示作用,常被用作判断市场长期方向和制定长期投资策略的依据。

        简单移动均线(SMA)定义与计算方法

          定义

简单移动均线(SMA)是通过计算特定时间段内证券价格的算术平均值来得到的。它反映了证券价格在一定时间周期内的平均变动情况,有助于交易者识别市场的趋势方向和支撑/阻力水平。接下来,将所选周期内的价格数据相加,然后除以数据的个数(即周期数),得到算术平均值。这个值就是该周期的简单移动均线。

          计算方法

首先,需要确定要计算的移动均线的周期,如5日、10日、20日等。这个周期通常根据交易者的个人偏好和市场特性来选择。

然后,收集在所选周期内每天的证券价格数据,如收盘价。

接下来,将所选周期内的价格数据相加,然后除以数据的个数(即周期数),得到算术平均值。这个值就是该周期的简单移动均线。

具体公式为:SMA = (C1 + C2 + C3 + ... + Cn) / n

其中,C1到Cn表示所选周期内的每天收盘价,n表示周期数。

        均线意义

  • 揭示市场趋势:均线能够清晰地描绘出市场的整体趋势,无论是上升趋势、下降趋势还是横向整理。
  • 提供买卖信号:均线之间的交叉常常被视为买卖信号
  • 评估支撑和阻力:均线不仅代表了过去一段时间内的平均价格,还可以作为市场未来的支撑和阻力水平
  • 辅助其他技术分析:均线常常与其他技术指标结合使用,以提高分析的准确性。例如,交易者可以结合相对强弱指数(RSI)、随机指标(KDJ)等来判断市场的超买超卖情况,并结合均线来捕捉买卖点。
  • 辅助决策制定:均线为交易者提供了客观的数据支持,有助于他们避免情绪化的交易决策。

均线策略方法论

        双均线策略

双均线策略运用短期移动平均线和长期移动平均线的相对位置关系,来判断市场的趋势和买卖时机。

        金叉和死叉的概念与确定买卖点

短期移动平均线(如5天平均线)对价格的变化更敏感,而长期移动平均线(如10天平均线)则更能反映出价格的总体趋势。当短期移动平均线上穿长期移动平均线时,形成的交叉点被称为“金叉”,这通常被视为买入信号;相反,当短期均线下穿长期均线时,形成的交叉点被称为“死叉”,这通常被视为卖出信号

代码实现准备

        开发环境

ANACONDA

        编程语言

Python

        开发环境搭建

Jupyter Notebook

        第三方库

tushare —— 股票数据获取
pandas —— 数据计算
numpy —— 数据计算
pandas_ta —— 技术指标计算
datetime —— 时间
matplotlib.pyplot —— 绘图

import tushare as ts
import pandas as pd
import numpy as np
import pandas_ta as ta
import datetime
import matplotlib.pyplot as plt

        数据获取

#初始化
token='你的token'
ts.set_token(token)
pro=ts.pro_api()


#定义获取股票函数
def get_stock(num):
    #获取股票代码
    stocknum=num
    #获取今天日期
    today = datetime.datetime.today() 
    #计算从今天起过去360天的日期
    startday=today+datetime.timedelta(days=-360)
    #使日期格式以年月日形式显示,如20241105
    today = today.strftime('%Y%m%d')
    startday =startday.strftime('%Y%m%d')
    #获取股票历史数据
    stock_df= pro.query('daily',ts_code=stocknum, start_date=startday,end_date=today)
    #把列trade_date数据转换为时间格式
    stock_df['trade_date'] = pd.to_datetime(stock_df['trade_date'])
    #把trade_date作为主索引
    stock_df.set_index('trade_date',inplace=True)
    #数据倒序显示
    stock_df=stock_df.iloc[::-1]
    return stock_df

#这里以科创板中芯国际为例
stock_df=get_stock('688981.SH')

这里以中芯国际为例,获取过去360天交易数据

f818bd8308c64984a8b6d8efc2ded4cb.png

      

双均线策略代码实现

        核心代码逻辑

5天线向上,突破10天线,金叉,收盘价高于5天线,买入
5天线向下,跌破10天线,死叉,收盘价低于5天线,卖出

        计算均线值的代码实现

# 5天线向上,突破10天线,金叉,收盘价高于5天线,买入
# 5天线向下,跌破10天线,死叉,收盘价低于5天线,卖出

#获取5天均线,10天均线数据
ma5_df = pd.DataFrame(ta.sma(stock_df['close'],length=5))
ma10_df = pd.DataFrame(ta.sma(stock_df['close'],length=10))

#将股票开盘价、收盘价、5天线、10天线数据汇总
total_df = pd.concat([stock_df['ts_code'],ma5_df,ma10_df,stock_df['close'],stock_df['open']],axis=1)


       根据均线判断买卖信号的代码

#当5天线大于10天线时且收盘价高于5天线,交易信号signal标记为1,反之标记为0
total_df['signal'] = np.where((total_df['SMA_5']>total_df['SMA_10']) & (total_df['close']>total_df['SMA_5']), 1,0)

#根据交易信号的变化下单,当交易信号从0变成1时买入,交易信号从1变成0时卖出,交易信号不变时不下单
total_df['order'] = total_df['signal'].diff()

892aa4ad71c34536a91498ba7cb7c46f.png

        示例展示

#创建尺寸为30*8的画布
plt.figure(figsize=(30,8))
#使用实线绘制股价(收盘价)
plt.plot(stock_df['close'],lw=2,label='price')
#使用虚线绘制5日均线
plt.plot(total_df['SMA_5'],lw=2,ls='--',label='SMA_5')
#使用-.风格绘制10日均线
plt.plot(total_df['SMA_10'],lw=2,ls='-.',label='SMA_10')
#将买入信号用正三角进行标示
plt.scatter(total_df.loc[total_df.order==1].index,stock_df['close'][total_df.order==1],marker = '^', s=80,color='r',label='Buy')
#将卖出信号用倒三角进行标示
plt.scatter(total_df.loc[total_df.order==-1].index,stock_df['close'][total_df.order==-1],marker = 'v', s=80,color='g',label='Sell')
#添加图注
plt.legend()
#添加网格以便于观察
plt.grid()
#显示图像
plt.show()
006917a0e511496ca9718580f4e162c7.png

价格图与买卖点

        简单回测效果

#初始资本 10000
initial_captial = 10000
#新建一个数据表positions,序号保持和total_df数据表一致
#用0将空值进行替换
positions = pd.DataFrame(index = total_df.index).fillna(0)
#因为A股买卖都是最低100股,对此设置stock字段为交易信号的100倍
positions['stock'] = total_df['signal'] * 100
#因为买卖点是以当天收盘价为判定依据,所以若符合买入卖出要求应是隔天操作,这里信号要后移一行
positions=positions.shift(1)
#创建投资组合数据表,用持仓的股票数量乘开盘价得出持仓的股票市值
portfolio = pd.DataFrame(index = total_df.index)
portfolio['stock value'] = positions.multiply(total_df['open'], axis=0)

#同样仓位的变化就是下单的数量
#用初始资金减去下单金额的总和就是剩余的资金
portfolio['cash'] = initial_captial - positions['stock'].diff().multiply(total_df['open'],axis=0).cumsum()
#剩余的资金+持仓股票市值即为总资产
portfolio['total'] = portfolio['cash'] + portfolio['stock value']
portfolio.tail(10)

#创建30*8的画布
plt.figure(figsize=(30,8))
#绘制总资产曲线
plt.plot(portfolio['total'], lw=2, label='total')
#绘制持仓股票市值曲线
plt.plot(portfolio['stock value'],lw=2,ls='--', label='stock value')
#添加图注
plt.legend()
#添加网格
plt.grid()
#展示图像
plt.show()

        代码解析 

1.因为A股买卖都是最低100股,对此设置stock字段为交易信号的100倍,对此positions['stock'] = total_df['signal'] * 100。

2.因为买卖点是以当天收盘价为判定依据,所以若符合买入卖出要求应是隔天操作,这里信号要后移一行,对此positions=positions.shift(1)。

3.在购入股票时用开盘价作为购入价,用持仓的股票数量乘开盘价得出持仓的股票市值,对此portfolio = pd.DataFrame(index = total_df.index)
portfolio['stock value'] = df.multiply(total_df['open'], axis=0)

         举例

假设10月16日出现买入信号,那么操盘时间就是10月17日以开盘价购入;

假设10月25日出现卖出信号,那么操盘时间就是10月26日以开盘价卖出。

c0fa240567ec49d084dea92d3ef8412d.png

24cac4879c5a4b18a09787d43864588d.png

回测效果

风险与注意事项

      市场风险对均线策略的影响

        均线策略的滞后性
均线策略是基于过去的价格数据来计算的,因此它总是滞后于市场的实际变化。

        均线策略产生更多假信号
市场风险增加时,市场价格的短期波动可能更加剧烈和频繁。这种波动可能导致均线频繁交叉,从而产生大量的买卖信号。

      趋势反转、震荡市场的问题

当市场趋势发生反转时(急升急跌),均线可能无法及时反映这一变化,导致投资者错过最佳的买卖时机。

市场处于震荡状态时(横盘整理),投资者如果盲目跟随这些信号进行交易,可能会频繁买卖,增加交易成本,甚至导致亏损。

总结

        完整代码如下

import tushare as ts
import pandas as pd
import numpy as np
import pandas_ta as ta
import datetime
import matplotlib.pyplot as plt


#初始化
token='你的token'
ts.set_token(token)
pro=ts.pro_api()


def get_stock(num):
    #获取股票代码
    stocknum=num
    #获取今天日期
    today = datetime.datetime.today() 
    #计算从今天起过去60天的日期
    startday=today+datetime.timedelta(days=-360)
    #使日期格式以年月日形式显示,如20241105
    today = today.strftime('%Y%m%d')
    startday =startday.strftime('%Y%m%d')
    #获取股票历史数据
    stock_df= pro.query('daily',ts_code=stocknum, start_date=startday,end_date=today)
    #把列trade_date数据转换为时间格式
    stock_df['trade_date'] = pd.to_datetime(stock_df['trade_date'])
    #把trade_date作为主索引
    stock_df.set_index('trade_date',inplace=True)
    #数据倒序显示
    stock_df=stock_df.iloc[::-1]
    return stock_df
 
stock_df=get_stock('688981.SH')

# 5天线向上,突破10天线,金叉,收盘价高于5天线,买入
# 5天线向下,跌破10天线,死叉,收盘价低于5天线,卖出

#获取5天均线,10天均线数据
ma5_df = pd.DataFrame(ta.sma(stock_df['close'],length=5))
ma10_df = pd.DataFrame(ta.sma(stock_df['close'],length=10))

#将股票开盘价、收盘价、5天线、10天线数据汇总
total_df = pd.concat([stock_df['ts_code'],ma5_df,ma10_df,stock_df['close'],stock_df['open']],axis=1)

#当5天线大于10天线时且收盘价高于5天线,交易信号signal标记为1,反之标记为0
total_df['signal'] = np.where((total_df['SMA_5']>total_df['SMA_10']) & (total_df['close']>total_df['SMA_5']), 1,0)

#根据交易信号的变化下单,当交易信号从0变成1时买入,交易信号从1变成0时卖出,交易信号不变时不下单
total_df['order'] = total_df['signal'].diff()


#创建尺寸为30*8的画布
plt.figure(figsize=(30,8))
#使用实线绘制股价(收盘价)
plt.plot(stock_df['close'],lw=2,label='price')
#使用虚线绘制5日均线
plt.plot(total_df['SMA_5'],lw=2,ls='--',label='SMA_5')
#使用-.风格绘制10日均线
plt.plot(total_df['SMA_10'],lw=2,ls='-.',label='SMA_10')
#将买入信号用正三角进行标示
plt.scatter(total_df.loc[total_df.order==1].index,stock_df['close'][total_df.order==1],marker = '^', s=80,color='r',label='Buy')
#将卖出信号用倒三角进行标示
plt.scatter(total_df.loc[total_df.order==-1].index,stock_df['close'][total_df.order==-1],marker = 'v', s=80,color='g',label='Sell')
#添加图注
plt.legend()
#添加网格以便于观察
plt.grid()
#显示图像
plt.show()

#初始资本 10000
initial_captial = 10000
#新建一个数据表positions,序号保持和total_df数据表一致
#用0将空值进行替换
positions = pd.DataFrame(index = total_df.index).fillna(0)
#因为A股买卖都是最低100股,对此设置stock字段为交易信号的100倍
positions['stock'] = total_df['signal'] * 100
#因为买卖点是以当天收盘价为判定依据,所以若符合买入卖出要求应是隔天操作,这里信号要后移一行
positions=positions.shift(1)
#创建投资组合数据表,用持仓的股票数量乘开盘价得出持仓的股票市值
portfolio = pd.DataFrame(index = total_df.index)
portfolio['stock value'] = df.multiply(total_df['open'], axis=0)

#同样仓位的变化就是下单的数量
#用初始资金减去下单金额的总和就是剩余的资金
portfolio['cash'] = initial_captial - df['stock'].diff().multiply(total_df['open'],axis=0).cumsum()
#剩余的资金+持仓股票市值即为总资产
portfolio['total'] = portfolio['cash'] + portfolio['stock value']
portfolio.tail(10)


#创建30*8的画布
plt.figure(figsize=(30,8))
#绘制总资产曲线
plt.plot(portfolio['total'], lw=2, label='total')
#绘制持仓股票市值曲线
plt.plot(portfolio['stock value'],lw=2,ls='--', label='stock value')
#添加图注
plt.legend()
#添加网格
plt.grid()
#展示图像
plt.show()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

宇文终君

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

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

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

打赏作者

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

抵扣说明:

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

余额充值