学习目标:择时策略1:一个金叉买入死叉卖出策略

学习内容:

1:导入必要的库

import pandas as pd
pd.set_option('expand_frame_repr', False)  # 当列太多时不换行
import matplotlib.pyplot as plt
import mplfinance as mpf #替换 import matplotlib.finance as mpf
import matplotlib#显示汉字
matplotlib.rc("font",family='YouYuan')#显示汉字

2:导入数据

# 导入数据
def import_stock_data(stock_code):"""只导入如下字段:'交易日期', '股票代码', '开盘价', '最高价', '最低价', '收盘价', '涨跌幅'最终输出结果按照日期排序:param stock_code::return:"""df = pd.read_csv(stock_code + '.csv', encoding='gbk')#print(df)df = df[['交易日期','股票代码', '开盘价', '最高价', '最低价', '收盘价', '涨跌幅']]df.sort_values(by=['交易日期'], inplace=True)df['交易日期'] = pd.to_datetime(df['交易日期'])df.reset_index(inplace=True, drop=True)return df

3:计算复权价

# 计算复权价
def cal_fuquan_price(input_stock_data, fuquan_type='后复权'):"""计算复权价:param input_stock_data::param fuquan_type:复权类型,可以是'后复权'或者'前复权':return:"""# 创建空的dfdf = pd.DataFrame()# 计算复权收盘价num = {'后复权': 0, '前复权': -1}price1 = input_stock_data['收盘价'].iloc[num[fuquan_type]]df['复权因子'] = (1.0 + input_stock_data['涨跌幅']).cumprod()price2 = df['复权因子'].iloc[num[fuquan_type]]df['收盘价_' + fuquan_type] = df['复权因子'] * (price1 / price2)# 计算复权的开盘价、最高价、最低价df['开盘价_' + fuquan_type] = input_stock_data['开盘价'] / input_stock_data['收盘价'] * df['收盘价_' + fuquan_type]df['最高价_' + fuquan_type] = input_stock_data['最高价'] / input_stock_data['收盘价'] * df['收盘价_' + fuquan_type]df['最低价_' + fuquan_type] = input_stock_data['最低价'] / input_stock_data['收盘价'] * df['收盘价_' + fuquan_type]return df[[i + '_' + fuquan_type for i in ['开盘价', '最高价', '最低价', '收盘价']]]

4:均线策略主体

# 普通均线策略
def signal_ma(df, ma_short=5, ma_long=15):"""均线策略:当短期均线由下向上穿过长期均线的时候,第二天以开盘价全仓买入并在之后一直持有股票。当短期均线由上向下穿过长期均线的时候,第二天以开盘价卖出全部股票并在之后一直空仓,直到下一次买入。:param df::param ma_short: 短期均线:param ma_long: 长期均线:return:"""# ===计算均线df['ma_short'] = df['收盘价_后复权'].rolling(ma_short, min_periods=1).mean()df['ma_long'] = df['收盘价_后复权'].rolling(ma_long, min_periods=1).mean()# ===找出买入信号# 当天的短期均线大于等于长期均线condition1 = (df['ma_short'] >= df['ma_long'])# 上个交易日的短期均线小于长期均线condition2 = (df['ma_short'].shift(1) < df['ma_long'].shift(1))# 将买入信号当天的signal设置为1df.loc[condition1 & condition2, 'signal'] = 1# ===找出卖出信号# 当天的短期均线小于等于长期均线condition1 = (df['ma_short'] <= df['ma_long'])# 上个交易日的短期均线大于长期均线condition2 = (df['ma_short'].shift(1) > df['ma_long'].shift(1))# 将买入信号当天的signal设置为0df.loc[condition1 & condition2, 'signal'] = 0# 将无关的变量删除df.drop(['ma_short', 'ma_long'], axis=1, inplace=True)return df# 加强均线斜率策略
def signal_ma_d(df, ma_short=5, ma_long=15):"""均线策略:当短期均线由下向上穿过长期均线的时候,第二天以开盘价全仓买入并在之后一直持有股票。当短期均线由上向下穿过长期均线的时候,第二天以开盘价卖出全部股票并在之后一直空仓,直到下一次买入。:param df::param ma_short: 短期均线:param ma_long: 长期均线:return:"""# ===计算均线df['ma_short'] = df['收盘价_后复权'].rolling(ma_short, min_periods=1).mean()df['ma_long'] = df['收盘价_后复权'].rolling(ma_long, min_periods=1).mean()# ===计算均线变化率df['ma_short_d']=df['ma_short']-df['ma_short'].shift(1)df['ma_long_d']=df['ma_long']-df['ma_long'].shift(1)# ===找出买入信号# 当天的短期均线大于等于长期均线condition1 = (abs(df['ma_short_d']) >= df['ma_long'])# ===找出买入信号# 当天的短期均线大于等于长期均线condition1 = (df['ma_short'] >= df['ma_long'])# 上个交易日的短期均线小于长期均线condition2 = (df['ma_short'].shift(1) < df['ma_long'].shift(1))# 将买入信号当天的signal设置为1df.loc[condition1 & condition2, 'signal'] = 1# ===找出卖出信号# 当天的短期均线小于等于长期均线condition1 = (df['ma_short'] <= df['ma_long'])# 上个交易日的短期均线大于长期均线condition2 = (df['ma_short'].shift(1) > df['ma_long'].shift(1))# 将买入信号当天的signal设置为0df.loc[condition1 & condition2, 'signal'] = 0# 将无关的变量删除df.drop(['ma_short', 'ma_long'], axis=1, inplace=True)return df

5:根据交易信号,计算每天的仓位

def position(df):"""根据交易信号,计算每天的仓位:param df::return:"""# 由signal计算出实际的每天持有股票仓位df['pos'] = df['signal'].shift()df['pos'].fillna(method='ffill', inplace=True)# 将涨跌停时不得买卖股票考虑进来# 找出开盘涨停的日期cond_cannot_buy = df['开盘价'] > df['收盘价'].shift(1) * 1.097  # 今天的开盘价相对于昨天的收盘价上涨了9.7%# 将开盘涨停日、并且当天position为1时的'pos'设置为空值df.loc[cond_cannot_buy & (df['pos'] == 1), 'pos'] = None# 找出开盘跌停的日期cond_cannot_sell = df['开盘价'] < df['收盘价'].shift(1) * 0.903  # 今天的开盘价相对于昨天的收盘价下得了9.7%# 将开盘跌停日、并且当天position为0时的'pos'设置为空值df.loc[cond_cannot_sell & (df['pos'] == 0), 'pos'] = None# position为空的日期,不能买卖。position只能和前一个交易日保持一致。df['pos'].fillna(method='ffill', inplace=True)# 在position为空值的日期,将position补全为0df['pos'].fillna(value=0, inplace=True)return df

6:计算资金曲线,简单版本

# 计算资金曲线,简单版本
def equity_curve_simple(df):"""最简单的计算资金曲线的方式,与实际不符合:param df::return:"""# ===计算实际资金曲线# 当当天空仓时,pos为0,资产涨幅为0# 当当天满仓时,pos为1,资产涨幅为股票本身的涨跌幅df['equity_change'] = df['涨跌幅'] * df['pos']# 根据每天的涨幅计算资金曲线df['equity_curve'] = (df['equity_change'] + 1).cumprod()return df

7:计算资金曲线,实用版本

# 计算资金曲线,实用版本
def equity_curve(df, initial_money=1000000, slippage=0.01, c_rate=5.0/10000, t_rate=1.0/1000):""":param df::param initial_money: 初始资金,默认为1000000元:param slippage: 滑点,默认为0.01元:param c_rate: 手续费,commission fees,默认为万分之5:param t_rate: 印花税,tax,默认为千分之1:return:"""# ===第一天的情况df.at[0, 'hold_num'] = 0  # 持有股票数量df.at[0, 'stock_value'] = 0  # 持仓股票市值df.at[0, 'actual_pos'] = 0  # 每日的实际仓位df.at[0, 'cash'] = initial_money  # 持有现金现金df.at[0, 'equity'] = initial_money  # 总资产 = 持仓股票市值 + 现金# ===第一天之后每天的情况for i in range(1, df.shape[0]):# 前一天持有的股票的数量hold_num = df.at[i - 1, 'hold_num']# 若发生除权,需要调整hold_numif abs((df.at[i, '收盘价'] / df.at[i - 1, '收盘价'] - 1) - df.at[i, '涨跌幅']) > 0.001:stock_value = df.at[i - 1, 'stock_value']last_price = df.at[i, '收盘价'] / (df.at[i, '涨跌幅'] + 1)hold_num = stock_value / last_pricehold_num = int(hold_num)# 判断是否需要调整仓位# 需要调整仓位if df.at[i, 'pos'] != df.at[i - 1, 'pos']:# 昨天的总资产 * 今天的仓位 / 今天的收盘价,得到需要持有的股票数theory_num = df.at[i - 1, 'equity'] * df.at[i, 'pos'] / df.at[i, '开盘价']# 对需要持有的股票数取整theory_num = int(theory_num)  # 向下取整数# 判断加仓还是减仓# 加仓if theory_num >= hold_num:# 计算实际需要买入的股票数量buy_num = theory_num - hold_num# 买入股票只能整百,对buy_num进行向下取整百buy_num = int(buy_num / 100) * 100# 计算买入股票花去的现金buy_cash = buy_num * (df.at[i, '开盘价'] + slippage)# 计算买入股票花去的手续费,并保留2位小数commission = round(buy_cash * c_rate, 2)# 不足5元按5元收if commission < 5 and commission != 0:commission = 5df.at[i, '手续费'] = commission# 计算当天收盘时持有股票的数量和现金df.at[i, 'hold_num'] = hold_num + buy_num  # 持有股票df.at[i, 'cash'] = df.at[i - 1, 'cash'] - buy_cash - commission  # 剩余现金# 减仓else:# 计算卖出股票数量,卖出股票可以不是整数,不需要取整百。sell_num = hold_num - theory_num# 计算卖出股票得到的现金sell_cash = sell_num * (df.at[i, '开盘价'] - slippage)# 计算手续费,不足5元按5元收并保留2位小数commission = round(max(sell_cash * c_rate, 5), 2)df.at[i, '手续费'] = commission# 计算印花税,保留2位小数。历史上有段时间,买入也会收取印花税tax = round(sell_cash * t_rate, 2)df.at[i, '印花税'] = tax# 计算当天收盘时持有股票的数量和现金df.at[i, 'hold_num'] = hold_num - sell_num  # 持有股票df.at[i, 'cash'] = df.at[i - 1, 'cash'] + sell_cash - commission - tax  # 剩余现金# 不需要调仓else:# 计算当天收盘时持有股票的数量和现金df.at[i, 'hold_num'] = hold_num  # 持有股票df.at[i, 'cash'] = df.at[i - 1, 'cash']  # 剩余现金# 计算当天的各种数据df.at[i, 'stock_value'] = df.at[i, 'hold_num'] * df.at[i, '收盘价']  # 剩余现金df.at[i, 'equity'] = df.at[i, 'cash'] + df.at[i, 'stock_value']  # 总资产df.at[i, 'actual_pos'] = df.at[i, 'stock_value'] / df.at[i, 'equity']  # 实际仓位return df

8:主体第一个模块:数据准备

# =====第一个模块:数据准备
# ===读入数据
code = 'sz300001'
#print(code)
df = import_stock_data(code)# 判断股票上市是否满一定时间,若不满足,则不运行策略
if df.shape[0] < 250:print ('股票上市未满一年,不运行策略')exit()# ===计算复权价
fuquan_type = '后复权'
df[[i + '_' + fuquan_type for i in ['开盘价', '最高价', '最低价', '收盘价']]] = cal_fuquan_price(df, fuquan_type)

9:主体2

# =====第二个模块:产生交易信号
# ===根据均线策略产生交易信号
df = signal_ma(df, ma_short=5, ma_long=15)
# =====第三个模块:根据交易信号计算每天的仓位
# ===计算仓位
df = position(df)
# ==截取上市一年之后的交易日
#df = df.iloc[250-1:]
# 将第一天的仓位设置为0
#df.iloc[0, -1] = 0
# =====第四个模块:根据仓位计算资金曲线
# ===简单方式
df_easy=equity_curve_simple(df)
# ===实际方式
df = df[['交易日期', '股票代码', '开盘价', '最高价', '最低价', '收盘价', '涨跌幅', 'pos']]
df.reset_index(inplace=True, drop=True)
df_difficult = equity_curve(df, initial_money=1000000, slippage=0.01, c_rate=5.0/10000, t_rate=1.0/1000)

10:主体3-绘图

# 对象式绘图
# pyplot模块中的figure()函数创建名为fig的Figure对象
fig = plt.figure(figsize=(12, 8))# 在Figure对象中创建一个Axes对象,每个Axes对象即为一个绘图区域
ax = fig.add_subplot(111)
ax.plot(df_difficult['交易日期'],df_difficult['equity'], '--r', lw=1)
ax.set_ylabel('Y 轴-资产',fontsize=15)
ax.set_xlabel('X 轴-时间',fontsize=15)
ax.axhline(y=1000000, c='blue', ls=':', lw=2)#均值水平线
# 设置标题
ax.set_title(u"均线金叉死叉交易策略",fontsize=25)

择时策略1:一个金叉死叉(python)相关推荐

  1. 【新一配】选股+择时策略组合

    [新一配]选股+择时策略组合 导语:本文讨论交易中两个非常重要的命题:选股+择时,并将其两者结合起来开发策略. 选股就是要选一只好股票,而择时就是选一个好的买卖时机.如果投资者选了一只很差劲的股票,无 ...

  2. 小散量化炒股记|趋势指标金叉死叉策略在震荡行情中怎么处理

    前言 相信大家都听说了量化交易这个东西了吧!量化交易是一种新兴的系统化金融投资方法. 那么,什么才是普通股民所适合的量化交易打开方式呢? 本文就用一个接地气的股票分析场景--典型的趋势指标金叉死叉策略 ...

  3. python量化 双均线策略(金叉死叉)

    #小策略,策略逻辑是在金叉时候买进,死叉时候卖出,所谓金叉死叉是两条均线的交叉,当短期均线上穿长期均线为金叉,反之为死叉 #下面是策略代码及结构 # 导入函数库 from jqdata import ...

  4. 用python找出400多万次KDJ金叉死叉,胜率有多高?附代码

    引言: 邢不行的系列帖子"量化小讲堂",通过实际案例教初学者使用python进行量化投Z,了解行业研究方向 这是邢不行第90期量化小课堂分享 作者 l 邢不行 不知道大家有没有发现 ...

  5. mt4双线macd_金叉死叉?高手教你MT4的MACD用法

    "日线金叉已经形成,后市即将走高,赶紧买吧!""4小时线形成死叉,价格即将走低,赶紧抛不然就来不及了!"传说中的金叉,死叉,到底是何方神圣,为何总是挂在各类交易 ...

  6. 扑克王怎样于市场中基于金叉死叉进行趋势跟踪

    扑克王怎样于市场中基于金叉死叉进行趋势跟踪 小孙我自己很久之前就对金融市场交易很感兴趣,从三年前开始,就不断地在理论实践两方面逐渐加深对于金融市场的理解,最近发现一个叫QR量化社区的平台,也给了自己很 ...

  7. 【量化】基于聚宽实现MACD均线择时策略

    MACD均线择时策略是十分基础的策略,适合咱们这种新手学习,这篇博客就分享一下基于聚宽实现MACD均线择时策略. 代码: 注:需要到聚宽的量化平台去运行. # MACD均线择时策略 ''' 筛选出符合 ...

  8. 金叉死叉图解,金叉死叉的短线操作方法

    小沙我自己长期以来一直对二级市场交易很有热情,从三年前开始,就不断地在理论实践两方面逐渐加深对于金融市场的理解,最近发现一个叫QR量化社区的平台,也给了自己很多灵感.经历了最近的市场波动,突然来了动力 ...

  9. 家庭主夫怎么在今年3月27号的市场中利用金叉死叉进行波段操作

    小孙我自己很久之前就对证券市场很感兴趣,从大学开始,就不断地在理论实践两方面逐渐加深对于金融市场的理解,最近发现一个叫QR量化社区的平台,也给了自己很多灵感.经历了最近的市场波动,心血来潮,在此就分享 ...

最新文章

  1. 计算机从网络上启动,如何设置计算机以从网络驱动器启动
  2. 变量声明和定义的区别
  3. ffmpeg转码速度控制方法
  4. (一)MVC5干货篇,目录和路由
  5. asp连接不到我mysql里_ASP连接MYSQL问题点解决
  6. 面试官问我:如何设计 QQ、微信等第三方账号登陆 ?
  7. pandas库基础笔记
  8. Spark部署模式入门
  9. Linux下安装python及MySQLdb
  10. 【数据结构06】二叉平衡树(AVL树)
  11. H3CNE中Vlan间路由
  12. 基于Basys2的数码管动态扫描module(verilog)的模块化设计
  13. [其他][转载]ACM知识点分类
  14. python的奇怪符号 -> 与 ...(点点点)
  15. SQLAlchemy黄金体验
  16. Chrome 印象笔记.剪裁登录弹出国际版
  17. python编程midi键盘按键错乱_电脑键盘按键错乱怎么回事 电脑键盘按键错乱原因【图文】...
  18. 干得漂亮!微信封禁大量色情账号
  19. 移植ethtool至ARM板
  20. Tensorflow Test1

热门文章

  1. linux--exec命令
  2. 深度完美 Ghost XP_SP3 软件选择版_2011.09
  3. 使用java中Scanner,Randon,ArrayList完成一个随机点名系统
  4. 客户端加JS代码判断复选框是否全选的代码
  5. Java学习: wait和notify方法、ThreadLocal
  6. Linux环境下多线程C/C++程序的内存问题诊断
  7. 龙芯杯系统能力竞赛CPU赛道参赛准备
  8. pngtree多达33000种ppt模板免费下载
  9. HOW TO:Be more productive aaron swartz
  10. php提取新闻图片,php新闻采集并生成图片