金融量化分析——双均线策略

文章介绍了使用Python和Tushare库进行股票数据采集,提取有效数据,计算5日和30日均线,通过金叉、死叉分析进行模拟交易策略,并展示了具体代码实现和模拟结果。最后讨论了未来改进方向和使用聚宽金融平台的实践应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、数据采集

二、提取有效数据

三、金叉、死叉分析

四、模拟实操

五、完整代码

六、未来展望


一、数据采集

1、首先安装Tushare:

pip install Tushare

2、使用Tushare接口,并导入所需的包:

import tushare as ts
import pandas as pd
import matplotlib as plt
import numpy as np
import mplfinance as mpf//绘制K线的包,本节没有用到

3、试着获取从2023-10-1到2023-11-1期间的茅台股票数据,:

df = pro.daily(ts_code='600519.SH', start_date='20231001', end_date='20231101')

4、将数据保存至CSV文件:

df.to_csv('600519data.csv',index=False)

二、提取有效数据

1、读取刚才保存的CSV文件,并选取所需数据:

df = pd.read_csv("600519data.csv",index_col='trade_date',parse_dates=['trade_date'])[['open','close','low','high']]

2、 由于所获得数据是时间倒序,所以需要按照时间标签正序排序

df = df.sort_index()

3、创建两列,并分别命名“ma5”和“ma30”,分别代表5日、30日均线的值:

df['ma5'] = np.nan
df['ma30'] = np.nan

for i in range(4,len(df)):
    df.loc[df.index[i],'ma5'] = df['close'][i-4:i+1].mean()

for i in range(29,len(df)):
    df.loc[df.index[i],'ma30'] = df['close'][i-29:i+1].mean()

也可使用另一种方法:

df['ma5'] = df['close'].rolling(5).mean
df['ma30'] = df['close'].rolling(30).mean

4、查看均线图:

df[['close','ma5','ma30']].plot()

三、金叉、死叉分析

1、创建两列数组,作为金叉和死叉:

若当日5日均线值大于等于30日均线值,并且前一日5日均线值小于30日均线值,则称交点为金叉.

若当日5日均线值小于等于30日均线值,并且前一日5日均线值大于30日均线值,则称交点为死叉.

golden_cross = []
death_cross = []
for i in range(1,len(df)):
    if df['ma5'][i]>=df['ma30'][i] and df['ma5'][i-1]<df['ma30'][i-1]:
        golden_cross.append(df.index[i])
    if df['ma5'][i]<=df['ma30'][i] and df['ma5'][i-1]>df['ma30'][i-1]:
        death_cross.append(df.index[i])

判定金叉、死叉另一种方法:

sr1 = df['ma5'] < df['ma30']
sr2 = df['ma5'] > df['ma30']
death_cross1 = df[sr1 & sr2.shift(1)].index
golden_cross1 = df[-(sr1 | sr2.shift(1))].index

左图为金叉,右图为死叉: 

四、模拟实操

        本文采取的双均线策略是选择5日和30日这两条移动平均线,当第一个金叉出现的时候买入,紧接着出现死叉的时候再卖出。

将两个存有金叉死叉数据的序列合并到一个序列sr里,

first_money = 100000
money = first_money
hold = 0 #持有多少股
sr1= pd.Series(1,index = golden_cross)
sr2 = pd.Series(0,index = death_cross)
sr = sr1._append(sr_death).sort_index()

for i in range(0,len(sr)):
    p =df['open'][sr.index[i]]
    if sr.iloc[i] == 1:
        #金叉
        buy = (money // (100 * p))
        hold += buy*100
        money -= buy*100*p
    else:
        money += hold *p
        hold = 0
p = df['open'][-1]
now_moeny = hold * p + money

print(now_moeny - first_money)

        结果显示,从2013年1月1日开始到2023年11月1日结束,在本金10w的情况下采取双均线策略,可以盈利1324734.0元,也就是132w+元。

五、完整代码

import tushare as ts
import pandas as pd
import matplotlib as plt
import numpy as np
import mplfinance as mpf

#读取数据
df = pd.read_csv("600519data.csv",index_col='trade_date',parse_dates=['trade_date'])[['open','close','low','high']]

#数据排序
df = df.sort_index()

#创建当日的5日和30日的均线值
df['ma5'] = np.nan
df['ma30'] = np.nan

for i in range(4,len(df)):
    df.loc[df.index[i],'ma5'] = df['close'][i-4:i+1].mean()

for i in range(29,len(df)):
    df.loc[df.index[i],'ma30'] = df['close'][i-29:i+1].mean()

#丢掉缺失数据
df = df.dropna()

#判断金叉、死叉
golden_cross = []
death_cross = []
for i in range(1,len(df)):
    if df['ma5'][i]>=df['ma30'][i] and df['ma5'][i-1]<df['ma30'][i-1]:
        golden_cross.append(df.index[i])
    if df['ma5'][i]<=df['ma30'][i] and df['ma5'][i-1]>df['ma30'][i-1]:
        death_cross.append(df.index[i])

#模拟实操
first_money = 100000
money = first_money
hold = 0 #持有多少股
sr1= pd.Series(1,index = golden_cross)
sr2 = pd.Series(0,index = death_cross)
sr = sr1._append(sr_death).sort_index()


for i in range(0,len(sr)):
    p =df['open'][sr.index[i]]
    if sr.iloc[i] == 1:
        #金叉
        buy = (money // (100 * p))
        hold += buy*100
        money -= buy*100*p
    else:
        money += hold *p
        hold = 0
p = df['open'][-1]
now_moeny = hold * p + money

print(now_moeny - first_money)

六、未来展望

        由于第二天才能知道昨天的收盘价,即使当天知道收盘价后也无法买入了,也就是说第二天才知道昨天是否有金叉死叉,所以实际操作中应该是后一天买入或者卖出。

        因此,在未来改进过程中可以将上述代码的p变量赋值第二天的开盘价格,以此来增加模拟策略的准确度。

七、拓展:利用聚宽金融量化交易平台

1、创建初始化函数

依旧选择贵州茅台股票,600519

# 初始化函数,设定基准等等
def initialize(context):
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    # 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    # 选取贵州茅台股票
    g.security = ['600519.XSHG']
    # 5日、60日
    g.p1 = 5
    g.p2 = 60

2、交易函数

(1)聚宽的attribute_history的函数:

一般只用前两个参数,第二个count参数为期望的最终数量。

  • count: 大于0的整数,表示获取bar的个数。如果行情数据的bar不足count个,返回的长度则小于count个数。

(2)账户信息函数

context.portfolio.positions,账户是否持仓。

context.portfolio.available_cash,账户鱼儿

(3)order_target函数,常用的依旧是前两个参数。

第二个参数可以填写账户金额,系数自动计算这些钱能买最大股票数。

def handle_data(context, data):
    for stock in g.security:
        # 金叉:如果5五日均线大于10日均线,并且不持仓
        # 死叉:如果5五日均线小于10日均线,并且持仓股票
        df = attribute_history(stock, g.p2)
        ma10 = df['close'].mean()
        ma5 = df['close'][-5:].mean()
        
        if ma10 > ma5 and stock in  context.portfolio.positions:
            # 死叉
            order_target(stock,0)
            
        if ma10 < ma5 and stock not in  context.portfolio.positions:
            # 金叉
            order_target(stock,context.portfolio.available_cash * 0.8)

3、完整代码

# 导入函数库
from jqdata import *

# 初始化函数,设定基准等等
def initialize(context):
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    # 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    # 选取贵州茅台股票
    g.security = ['600519.XSHG']
    # 5日、60日
    g.p1 = 5
    g.p2 = 60
## 开盘前运行函数
def handle_data(context, data):
    for stock in g.security:
        # 金叉:如果5五日均线大于10日均线,并且不持仓
        # 死叉:如果5五日均线小于10日均线,并且持仓股票
        df = attribute_history(stock, g.p2)
        ma10 = df['close'].mean()
        ma5 = df['close'][-5:].mean()
        
        if ma10 > ma5 and stock in  context.portfolio.positions:
            # 死叉
            order_target(stock,0)
            
        if ma10 < ma5 and stock not in  context.portfolio.positions:
            # 金叉
            order_target(stock,context.portfolio.available_cash * 0.8)

4、运行结果

时间选择的是2022-10-1至2023-10-1,可以看到一年时间收益4.46%。

至于双均线策略是否有用,小伙伴们还可多换些股票和时间区间来验证。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

流离川

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

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

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

打赏作者

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

抵扣说明:

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

余额充值