[程序分享] 股市风起云涌,我用Python分析周期之道
来自:MACD论坛(bbs.shudaoyoufang.com)
作者:alxbj
浏览:20297
回复:7
本帖最后由 alxbj 于 2019-1-8 22:47 编辑
正文股票市场周期是股票市场长期的价格模式,通常与商业周期有关。 它是技术分析的关键,其中投资方法基于周期或重复的价格模式。 如果我们对股市周期有了更好的理解,我们总能以相对低的价格买入并在每个周期以相对较高的价格卖出,将始终获得正的回报。当然,股票市场没有什么策略可以永远赚钱,但我们基于Python,可以帮助我们更深入、快速地了解隐藏在股市中的周期。
fbprophet简介Fbprophet是Facebook发布的一个开源软件,旨在为大规模预测提供一些有用的指导。 默认情况下,它会将时间序列划分为趋势和季节性,可能包含年度,周度和每日。 但是,分析师可以定义自己的季节性。 为了更好地理解该库,先导文件是非常有用的。
该库的一个特点是简单性、灵活性。 由于我们想要计算的股票市场周期不限于每年,每周或每日,我们应该定义自己的周期,找出哪些更适合数据。 此外,由于周末没有交易,我们不应该使用每周季节性。 我们还可以通过addseasonality函数定义'selfdefine_cycle'。 所有设置只需两行代码即可完成。
- m = Prophet(weekly_seasonality=False,yearly_seasonality=False)
- m.add_seasonality('self_define_cycle',period=8,fourier_order=8,mode='additive')
[color=rgb(51, 102, 153) !important]复制代码
以Costco为例我们可以使用Costco标的从2015/10/1到2018/10/1, 使用pandas_datareader,我们可以快速读取股票价格。如下图: 地址:https://pandas-datareader.readth ... st/remote_data.html
在下图中,我们可以看到从2015年开始有一个强劲的价格增长趋势。然而,在中途仍然存在很多上下周期波动,这些周期都是我们的赚钱点。 - ticker = "COST"
- start_date = '2015-10-01'
- end_date = '2018-10-01'
- stock_data = data.DataReader(ticker, 'iex', start_date, end_date)
- stock_data['close'].plot(figsize=(16,8),color='#002699',alpha=0.8)
- plt.xlabel("Date",fontsize=12,fontweight='bold',color='gray')
- plt.ylabel('Price',fontsize=12,fontweight='bold',color='gray')
- plt.title("Stock price for Costco",fontsize=18)
- plt.show()
[color=rgb(51, 102, 153) !important]复制代码
对于预测模型,评估它们的一种方法是样本均方误差。 我们可以使用2015/10/1至2018/3/31进行训练,并保留最后6个月的数据进行测试和计算样本均方误差。 在每个周期内,我们可以通过以最低价格买入并以最高价格卖出的方式来优化我们的回报。 为了简化过程,我们使用自定义函数cycle_analysis。 输出是一个列表,其中包含每个周期的预计回报和样本均方误差。 - data:带有时间索引的Pandas数据
- split_date:分割训练和测试数据的日期cycle:每个周期的间隔(天)
- cycle:每个周期的间隔(天)
- mode:季节性的加法或乘法(可选)
- forecast_plot:是否打印预测图(可选,默认为False)
- print_ind:是否打印每个周期的预计回报和是否采样均方误差(可选,默认为False)
- def cycle_analysis(data,split_date,cycle,mode='additive',forecast_plot = False,print_ind=False):
- training = data[:split_date].iloc[:-1,]
- testing = data[split_date:]
- predict_period = len(pd.date_range(split_date,max(data.index)))
- df = training.reset_index()
- df.columns = ['ds','y']
- m = Prophet(weekly_seasonality=False,yearly_seasonality=False,daily_seasonality=False)
- m.add_seasonality('self_define_cycle',period=cycle,fourier_order=8,mode=mode)
- m.fit(df)
- future = m.make_future_dataframe(periods=predict_period)
- forecast = m.predict(future)
- if forecast_plot:
- m.plot(forecast)
- plt.plot(testing.index,testing.values,'.',color='#ff3333',alpha=0.6)
- plt.xlabel('Date',fontsize=12,fontweight='bold',color='gray')
- plt.ylabel('Price',fontsize=12,fontweight='bold',color='gray')
- plt.show()
- ret = max(forecast.self_define_cycle)-min(forecast.self_define_cycle)
- model_tb = forecast['yhat']
- model_tb.index = forecast['ds'].map(lambda x:x.strftime("%Y-%m-%d"))
- out_tb = pd.concat([testing,model_tb],axis=1)
- out_tb = out_tb[~out_tb.iloc[:,0].isnull()]
- out_tb = out_tb[~out_tb.iloc[:,1].isnull()]
- mse = mean_squared_error(out_tb.iloc[:,0],out_tb.iloc[:,1])
- rep = [ret,mse]
- if print_ind:
- print "Projected return per cycle: {}".format(round(rep[0],2))
- print "MSE: {}".format(round(rep[1],4))
- return rep
[color=rgb(51, 102, 153) !important]复制代码
在下面两个图中,我们将两种不同cycle(30和300)分别应用于Costco股票价格,并将2018/4/1作为训练和测试的分割日期。 正如我们所看到的,如果我们选择一个较短的长度(例如30天),则一个周期内的回报是很小的,我们需要经常进行交易,如果我们选择较长的长度,它会延长我们的预测(例如300天)。 |