赞
踩
目录
“低买高卖”策略。每次都在相对低点买入,并且在相对高点卖出(跌了买,涨了卖)。下面进行简单回测:
1.导入库
- # 导入库
- from pandas_datareader import data as dt
- import yfinance as yf
- yf.pdr_override()
-
- import pandas as pd
- import numpy as np
- import matplotlib.pyplot as plt
- import seaborn as sns
2.获取数据
- start_date = '2020-01-01'
- end_date = '2020-03-20'
-
- # 提取数据:中国平安股票数据
- zgpa = dt.get_data_yahoo('601318.ss',start_date,end_date)
- zgpa.head()
输出:
3.设定交易信号
- # 交易信号
- zgpa_signanl = pd.DataFrame(index = zgpa.index) # 日期index
- zgpa_signanl['price'] = zgpa['Adj Close'] # 调整价格作为股票价格
- zgpa_signanl['diff'] = zgpa_signanl['price'].diff() #股价变化
- zgpa_signanl = zgpa_signanl.fillna(0.0) #第一个空值填充为0
- zgpa_signanl['signal'] = np.where(zgpa_signanl['diff']>=0,0,1) #股价上涨或不变记为0,下跌记为1
- zgpa_signanl['order'] = zgpa_signanl['signal'].diff()*100 #买入/卖出1手(100股),股价上涨:卖出,股价下跌:买入
- zgpa_signanl.head()
输出:
4.回测
- # 回测
- initial_cash = 20000.00 # 初始资金2万元
- # 股票市值
- zgpa_signanl['stock'] = zgpa_signanl['order']*zgpa_signanl['price']
- # 剩余现金=初始现金-现金流变化的累加
- zgpa_signanl['cash'] = initial_cash -(zgpa_signanl['order'].diff()*zgpa_signanl['price']).cumsum()
- #总资产=股票+现金
- zgpa_signanl['total'] = zgpa_signanl['stock'] +zgpa_signanl['cash']
-
- # 绘图
- plt.figure(figsize=(8,5))
- plt.plot(zgpa_signanl['total'],label = 'total') #总资产
- plt.plot(zgpa_signanl['order'].cumsum()*zgpa_signanl['price'],'--',label = 'stock value') #持仓股票市值
- plt.grid(True)
- plt.legend(loc='center right')
- plt.show()
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
输出:
当股价上升且向上穿过N日的均线时,说明股价向上突破,此时下单买入;当股价下降且向下穿过N日均线,说明股价出现下跌趋势,此时下单卖出。或者当M日均价上升穿过N日的均线(M < N)时,说明股票处上升的趋势,下单买入;反之,当M日均价下降且穿过N日均线时,说明股票处于下降趋势,下单卖出。
1.这里指标使用10日均线:
- period = 10 #10日均线
- avg_10=[] # 储存10天的价格
- avg_value=[] # 储存10天价格的均值
- for price in zgpa['Adj Close']:
- avg_10.append(price)
- if len(avg_10) >period:
- del avg_10[0]
- avg_value.append(np.mean(avg_10))
-
- # 将10日均价写到股票价格数据表中
- zgpa = zgpa.assign(avg_10 = pd.Series(avg_value, index= zgpa.index))
- zgpa.head()
输出:
2.画个10日均线的图
- plt.figure(figsize=(10,6))
- plt.plot(zgpa['Adj Close'],lw = 2,c ='k',label = 'stock price') # stock price,股价
- plt.plot(zgpa['avg_10'],'--',lw =2 ,c ='b',label = 'avg_10') # avg_10,10日均价
- plt.grid(True)
- plt.legend()
- plt.show()
输出:
使用两条均线判断股价未来的走势。一条是长期均线(如20日均线),另一条是短期均线(如5日均线)。这种策略基于这样一种假设:股票价格的动量会朝着短期均线的方向移动。当短期均线穿过过长期均线,超过长期移动平均线时,动量将向上,此时股价可能会上涨。然而,如果短期均线的移动方向相反,则股价可能下跌。
1.策略代码:
- strategy = pd.DataFrame(index=zgpa.index)
- strategy['signal'] = 0 # 存储交易信号
- strategy['avg_5'] = zgpa['Adj Close'].rolling(5).mean() # 5日均价
- strategy['avg_10'] = zgpa['Adj Close'].rolling(10).mean() # 10日均价
- strategy['signal'] = np.where(strategy['avg_5']>strategy['avg_10'],1,0) # 5日均价avg_5>10日均价avg_10时动量向上,股价可能上涨,标记为1(avg_5<avg_10时,股价可能下跌,标记为0)
- strategy['order'] = strategy['signal'].diff() # 信号从0变1,买入,从1变0,卖出
- strategy
输出:
2.画个图看看该策略在哪里买/卖
- plt.figure(figsize=(10,5))
- plt.plot(zgpa['Adj Close'],lw = 2,label = 'price') # stock price
- plt.plot(strategy['avg_5'],lw = 2,ls ='--',label = 'avg5') # stock price
- plt.plot(strategy['avg_10'],lw = 2,ls ='-.',label = 'avg10') # stock price
- plt.scatter(strategy.loc[strategy['order']==1].index,
- zgpa['Adj Close'][strategy['order']==1],
- marker='^',s = 80, c = 'r', label = 'Buy') # 标出买入信号
- plt.scatter(strategy.loc[strategy['order']==-1].index,
- zgpa['Adj Close'][strategy['order']==-1],
- marker='v',s = 80, c = 'g', label = 'Sell') # 标出卖出信号
- plt.legend()
- plt.grid(True)
- plt.show()
输出:
3.对该策略回测:
- ## 回测
- initial_cash = 20000.00 # 初始资金2万元
- positions = pd.DataFrame(index = strategy.index).fillna(0)
- positions['stock'] = strategy['signal']*100 # 买卖1手100股
- portfolio = pd.DataFrame()
- portfolio['stock value'] = positions.multiply(zgpa['Adj Close'], axis = 0) # 持仓股票*股价=股票市值
- # multiply 对应位置上两个对象元素的乘积
- order = positions.diff() # 下单数量
- # 剩余资金 = 初始资金 - 下单金额的总和
- portfolio['cash'] = initial_cash - order.multiply(zgpa['Adj Close'], axis = 0).cumsum()
- # 总资产 = 剩余资金 + 持仓股票市值
- portfolio['total'] = portfolio['cash'] + portfolio['stock value']
-
- portfolio
输出(看看portfolio):
画个图看下:
- plt.figure(figsize=(10,5))
- plt.plot(portfolio['total'], lw=2, label = 'total') # 总资产
- plt.plot(portfolio['stock value'], lw=2, label = 'stock value') # 持仓股票市值
- plt.legend()
- plt.grid(True)
- plt.show()
该时间区间市场下跌,该策略总体上还是亏钱的。
在股价超过过去N个交易日的股价最高点时买入,在股价低于过去N个交易日的股价最低点时卖出。上述的若干个最高点和最低点会组成一个通道,称“唐奇安通道”。
使用过去N天的股价最高点和过去N天的股价最低点生成唐奇安通道。一般来说,N会设置为20。不过因为我们下载的股票数据时间范围跨度比较小,所以选择了使用过去5日的股价最高点和最低点来进行演示。
1.策略信号:
- turtle = pd.DataFrame(index= zgpa.index)
- turtle['high'] = zgpa['Adj Close'].shift(1).rolling(5).max()
- turtle['low'] = zgpa['Adj Close'].shift(1).rolling(5).min()
- turtle['buy'] = zgpa['Adj Close'] > turtle['high'] #股价突破上沿,买入
- turtle['sell'] = zgpa['Adj Close'] < turtle['low'] #股价突破下沿,卖出
- turtle
输出:
2.根据交易信号和仓位进行下单
交易信号为“买入”且空仓时,才下买入订单;交易信号为“卖出”且有持仓股票时,才会下卖出订单
- turtle['orders'] = 0 # 初始订单状态为0
- position = 0 # 初始仓位0
- for k in range(len(turtle)):
- if turtle.buy[k] and position == 0: # 买入信号为true且空仓时买入1手:
- turtle.orders[k] = 1
- position = 1
- elif turtle.sell[k] and position > 0:
- turtle.orders[k] = -1
- position = 0
-
- turtle
输出:
3.画图看下买/卖时机:
- plt.figure(figsize=(10, 5))# 设置画布的尺寸0
- plt.plot(zgpa['Adj Close'], lw=2, label='stock') #股价折线图
- # 唐奇安通道的上沿
- plt.plot(turtle['high'], lw=2, ls='--',c='r', label='high')
- # 唐奇安通道的下沿
- plt.plot(turtle['low'], lw=2, ls='--',c='g', label='low')
- #将买入信号用正三角标识
- plt.scatter(
- turtle.loc[turtle.orders == 1].index,
- zgpa['Adj Close'][turtle.orders == 1],
- marker='^', s=80, c='r', label='buy')
- #将卖出信号用倒三角标识
- plt.scatter(turtle.loc[turtle.orders == -1].index,
- zgpa['Adj Close'][turtle.orders == -1],
- marker='v', s=80, c='g', label='shell')
-
- plt.legend()
- plt.grid()
- plt.show()
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
输出:
4.回测:
- # 回测
-
- # 初始资金
- initial_cash = 20000
- # 创建新的数据表,序号和turtle数据表一致
- positions = pd.DataFrame(index=turtle.index).fillna(0.0)
- # 每次交易为1手(100股),仓位既买单和卖单的累积加和
- positions['stock'] = 100 * turtle['orders'].cumsum()
- # 创建投资组合数据表
- portfolio = positions.multiply(zgpa['Adj Close'], axis=0)
- # 持仓市值为持仓股票数乘以股价
- portfolio['holding_values'] = positions.multiply(zgpa['Adj Close'], axis=0)
- # 计算出仓位的变化
- pos_diff = positions.diff()
- # 剩余的现金是初始资金减去仓位变化产生的现金流累计加和
- portfolio['cash'] = initial_cash - (pos_diff.multiply(zgpa['Adj Close'], axis=0)).cumsum()
- # 总资产既持仓股票市值加剩余现金
- portfolio['total'] = portfolio['cash'] + portfolio['holding_values']
- portfolio
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
输出:
画图看下:
-
- #画图
- plt.figure(figsize=(10, 5))
- plt.plot(portfolio['total'], label='total')
- plt.plot(portfolio['holding_values'], '--', label='holding_values') #持仓股票是市值
- plt.legend()
- plt.grid()
- plt.show()
输出:
可以看到该策略还是亏钱(最后剩余19549元)的。但是比双移动平均策略(剩余19413元)赔的少一些,表明该策略更优。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。