Finished Chap2 Deciphering the Market with Technical Analysis
|
@ -0,0 +1,2 @@
|
||||||
|
.vscode
|
||||||
|
**.pdf
|
|
@ -0,0 +1,280 @@
|
||||||
|
# Chap 2. Deciphering the Markets with Technical Analysis (使用技术分析来解密市场)
|
||||||
|
|
||||||
|
本章目标:
|
||||||
|
|
||||||
|
* 介绍流行的技术分析方法
|
||||||
|
* 展示如何用来分析市场数据
|
||||||
|
|
||||||
|
创造交易策略的基础:我们假设市场会不断重复自身。通过分析过往记录,市场数据的技术分析可分为两块:
|
||||||
|
|
||||||
|
* chart pattern (图表): 此类技术分析通过识别交易的模式并预测他们何时会重复。比较应用于算法交易
|
||||||
|
* technical indicator (技术指标): 使用数学来预测金融市场走向。指标有很多但可被归纳为
|
||||||
|
* trend (趋势)
|
||||||
|
* momentum (动量)
|
||||||
|
* volume (体量)
|
||||||
|
* volatility (波动)
|
||||||
|
* support and resistance (支撑与阻力)
|
||||||
|
|
||||||
|
## 1. Designing a trading strategy based on trend- and momentum-based indicator (设计一个基于趋势和动能的指标)
|
||||||
|
|
||||||
|
“趋势交易策略关注速度,动能交易策略关注加速度”
|
||||||
|
|
||||||
|
* 趋势交易:
|
||||||
|
* 在分析历史价格数据时,如果价格不断上涨一定时间(天),我们就开多头仓位
|
||||||
|
* 动能交易:
|
||||||
|
* 基于过往行为的强度来挂单
|
||||||
|
* price momentum 是一个价格动作的量
|
||||||
|
* 逻辑:an asset price with a strong movement in a given direction will keep going in the same direction in the future.
|
||||||
|
|
||||||
|
### 1.1 Support and resistance indicators (支撑线、阻力线)
|
||||||
|
|
||||||
|
* 当价格下跌到一定程度时,会有集中的需求导致下跌停止。当价格上涨到一定程度时,会有集中性的供给导致价格无法上升
|
||||||
|
* Support line = 价格下跌的下限
|
||||||
|
* Resistance line = 价格上涨的上限
|
||||||
|
* 利用了买低卖高的市场心理
|
||||||
|
|
||||||
|
![](sources/sec2/supportresistanceline.png)
|
||||||
|
|
||||||
|
* 获取2015-07-01 至2018-01-01的GOOGLE的股票价格。
|
||||||
|
* 画出了 support line (红线), resistence line (绿线)
|
||||||
|
* 蓝线表示数据积累点 (200天)
|
||||||
|
|
||||||
|
基于这个简单的技术分析,我们可以定出策略,在200天的数据积累后(蓝色虚线):
|
||||||
|
|
||||||
|
* 股价高至 resistence line 后,挂空头仓位 (short the stock).
|
||||||
|
* 股价低至 support line 后,挂多头仓位 (long the stock).
|
||||||
|
|
||||||
|
实际效果:
|
||||||
|
|
||||||
|
* 2016-08 后,GOOG 股价触发 resistance line, 算法开始持续做空 GOOGLE, 损失惨重。
|
||||||
|
|
||||||
|
分析:
|
||||||
|
|
||||||
|
* 即便 support & resistance indicator 有经济学逻辑,实际中需要对其进行矫正。例如:移动 support/resistance line.
|
||||||
|
|
||||||
|
改进(增加特性):
|
||||||
|
|
||||||
|
* 使用 rolling window 滚动窗口
|
||||||
|
* 数股价触及支撑线或阻力线的数量
|
||||||
|
* 加入 tolerance margin, 从而把支撑/阻力线的空间缩小(如下图)
|
||||||
|
|
||||||
|
![](../img/2_1.jpg)
|
||||||
|
|
||||||
|
方案选择(增加两种参数):
|
||||||
|
|
||||||
|
* 价格触及 supporting/resistance line 的最少次数
|
||||||
|
* 定一个 tolorance margine
|
||||||
|
|
||||||
|
```
|
||||||
|
price sup_tolerance res_tolerance sup_count res_count sup res position signal
|
||||||
|
Date
|
||||||
|
2013-12-31 558.262512 NaN NaN NaN NaN NaN NaN NaN NaN
|
||||||
|
2014-01-02 554.481689 NaN NaN NaN NaN NaN NaN NaN NaN
|
||||||
|
2014-01-03 550.436829 NaN NaN NaN NaN NaN NaN NaN NaN
|
||||||
|
2014-01-06 556.573853 NaN NaN NaN NaN NaN NaN NaN NaN
|
||||||
|
2014-01-07 567.303589 NaN NaN NaN NaN NaN NaN NaN NaN
|
||||||
|
... ... ... ... ... ... ... ... ... ...
|
||||||
|
2017-12-22 1060.119995 1014.371997 1061.44801 NaN NaN 998.679993 1077.140015 0.0 1.0
|
||||||
|
2017-12-26 1056.739990 1014.371997 1061.44801 NaN NaN 998.679993 1077.140015 0.0 1.0
|
||||||
|
2017-12-27 1049.369995 1014.371997 1061.44801 NaN NaN 998.679993 1077.140015 0.0 1.0
|
||||||
|
2017-12-28 1048.140015 1014.371997 1061.44801 NaN NaN 998.679993 1077.140015 0.0 1.0
|
||||||
|
2017-12-29 1046.400024 1014.371997 1061.44801 NaN NaN 998.679993 1077.140015 0.0 1.0
|
||||||
|
```
|
||||||
|
|
||||||
|
代码完成:
|
||||||
|
|
||||||
|
1. 在规定的滚动时间窗口内(默认20天)基于过去的数据计算支撑线、阻力线。
|
||||||
|
2. 基于支撑线、阻力线,计算了20%的区域。
|
||||||
|
3. 用diff()计算了下单的时间
|
||||||
|
4. 当价格低于支撑线,到达支撑区间后(或者高于阻力线,到达阻力区间),我们会挂多头仓位(空头仓位)
|
||||||
|
|
||||||
|
![](sources/sec2/supportresistanceline_improved.png)
|
||||||
|
|
||||||
|
交易策略:
|
||||||
|
|
||||||
|
* 当价格进入支撑线区域后连续两天,就可以买多仓
|
||||||
|
* 价格进入阻力线区域后连续两天,买空仓
|
||||||
|
|
||||||
|
## 2. Creating trading signals based on fundamental technical analysis (基于基本技术分析的交易算法)
|
||||||
|
|
||||||
|
常用技术分析方法(指标):
|
||||||
|
|
||||||
|
* Simple Moving Average (SMA) 简单移动平均线
|
||||||
|
* Exponential Moving Average (EMA) 指数移动平均线
|
||||||
|
* Absolute Price Oscillator (APO) 绝对价格震荡器
|
||||||
|
* Moving Average Convergence Divergence (MACD) 指数平滑移动平均线
|
||||||
|
* Bollinger Bands (BBANDS) 布林线指标
|
||||||
|
* Relative Strength Indicator (RSI) 相对强弱和是
|
||||||
|
|
||||||
|
* EMA是非常常用的时间序列技术指标
|
||||||
|
* 类似于SMA,但是对价格的权重不是平均的
|
||||||
|
* 背后的概念:
|
||||||
|
* 若模型使用“时间约近,权重越高”:追求更新的信息
|
||||||
|
* 若模型使用“时间越远,权重越高”:认为 longer-term trends 含有更多信息
|
||||||
|
* 时间窗口:
|
||||||
|
* 越短:EMA 对新数据的反映越大; i.e. **Fast EMA**
|
||||||
|
* 越长:EMA 对新数据的反映月满; i.e. **Slow EMA**
|
||||||
|
|
||||||
|
#### 基于旧EMA计算新EMA
|
||||||
|
|
||||||
|
$$EMA = (P - EMA_{old})\times \mu + EMA_{old}$$
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
$$EMA = P \times \mu + (1-\mu) \times EMA_{old}$$
|
||||||
|
|
||||||
|
where:
|
||||||
|
|
||||||
|
* $P$ = 新的(当今)价格
|
||||||
|
* $/pu$ = **smoothing factor**; 新的价格数据的 weight factor (权重), 经常被设置为 $\frac{2}{(n+1)}$
|
||||||
|
* $N$ = 时间
|
||||||
|
* $EMA_{old}$ = 之前的EMA数值
|
||||||
|
|
||||||
|
![](sources/sec2/ema.png)
|
||||||
|
|
||||||
|
* EMA 和 SMA 一样具有平滑作用,因此减少了噪音
|
||||||
|
* EMA 中具有的 $\mu$ & $N$,可以让我们控制新进数据的权重。可以让我们通过不同的 $\mu$ & $N$ 建立不同的EMA
|
||||||
|
|
||||||
|
### 2.3 绝对价格震荡器 (APO)
|
||||||
|
|
||||||
|
* APO 为一种技术指标:通过价格的移动平均数值来捕捉价格在短期内的背离
|
||||||
|
* 计算方法:计算 Fast EMA 和 Slow EMA 时间的价差。
|
||||||
|
* 背后的逻辑:试图衡量 $EMA_{fast}$ 背离 $EMA_{slow}$ 多远。更大的背离标志着两种情况
|
||||||
|
* 金融资产价格开始出现趋势或者准备爆发
|
||||||
|
* 金融资产价格已经偏离平衡,要么是被低估或者高估
|
||||||
|
|
||||||
|
$$APO = EMA_{fast} - EMA_{slow}$$
|
||||||
|
|
||||||
|
下面案例使用了 $N=2/11$ 和 $N=2/41$ 的 APO
|
||||||
|
|
||||||
|
![](sources/sec2/apo.png)
|
||||||
|
|
||||||
|
* $EMA_{fast}$ 对新价格的的波动性更敏感,而 $SMA_{slow}$ 衰退得更加慢
|
||||||
|
* 当股价价格向上爆发的时候 APO 为正;而且爆发程度越强 APO 绝对值越高
|
||||||
|
|
||||||
|
这个信号可以用来做交易策略
|
||||||
|
|
||||||
|
### 2.4 指数平滑移动平均线 (MACD)
|
||||||
|
|
||||||
|
* MACD 是一种基于APO的指标
|
||||||
|
* 计算方法:
|
||||||
|
* 在计算 APO 后,我们对其再做一次 EMA,从而得到一个MACD信号 ($MACD_{Signal}$)
|
||||||
|
* 或者,在$MACD_{Signal}$基础上生成histogram
|
||||||
|
|
||||||
|
$$MACD = EMA_{Fast} - EMA_{Slow}$$
|
||||||
|
$$MACD_{Signal} = EMA_{MACD}$$
|
||||||
|
$$MACD_{Histogram} = MACD-MACD_{Signal}$$
|
||||||
|
|
||||||
|
一个成功的 $MACD_{signal}$ 可以捕获金融产品的方向、趋势和时间长度
|
||||||
|
|
||||||
|
![](sources/sec2/macd.png)
|
||||||
|
|
||||||
|
* $EMA_{MACD}$ 在 MACD(APO)上在加了一层平滑。
|
||||||
|
* $MACD_{Histogram}$ 捕获了两个点:
|
||||||
|
* 趋势开始或者回归的时间
|
||||||
|
* 当$MACD_{Histogram}$值在反转正负以后,趋势持续的强度 (magnitude of lasting trends when $MACD_{Histogram}$ values stay positive or negative after reversing signs)
|
||||||
|
|
||||||
|
### 2.5 布林线指标 (BBANDS)
|
||||||
|
|
||||||
|
Bollinger Bands:
|
||||||
|
|
||||||
|
* 一种著名的技术分析指标,由 John Bollinger 发明
|
||||||
|
* 计算方式(类似 6-sigma):
|
||||||
|
* 1. 使用一个时间窗口,计算 moving average (SMA, EMA 都可)
|
||||||
|
* 2. 计算这个时间窗口的 standard deviation
|
||||||
|
* 3. Upper Band = moving average 加上 standard deviation 的倍数
|
||||||
|
* 4. Lower Band = moving average 减去 standard deviation 的倍数
|
||||||
|
* BBAND 代表了对价格波动性的预估。若价格到了BBAND之外,那就是一个交易信号。
|
||||||
|
|
||||||
|
$$BBAND_{Middle} = SMA_{n-periods}$$
|
||||||
|
|
||||||
|
* Lower Bollinger band $BBAND_{Middle}$ 是前n个时段的SMA (.e.g. 过去n天)
|
||||||
|
|
||||||
|
$$BBAND_{Upper} = BBAND_{Middle} + (\beta * \delta)$$
|
||||||
|
$$BBAND_{Lower} = BBAND_{Middle} - (\beta * \delta)$$
|
||||||
|
|
||||||
|
* $\delta$ 是standard deviation
|
||||||
|
* $\beta$ 是 standard deviation factor,由我们选择; $\beta$ 越大,BBAND越大
|
||||||
|
|
||||||
|
![](../bbands.png)
|
||||||
|
|
||||||
|
### 2.6 相对强弱指标 (RSI)
|
||||||
|
|
||||||
|
* RSI通过比较一段时期内的平均收盘涨数和平均收盘跌数来分析市场买沽盘的意向和实力,从而作出未来市场的走势
|
||||||
|
* RSI在1978年6月由Wells Wider创制的一种通过特定时期内股价的变动情况计算市场买卖力量对比,来判断股票价格内部本质强弱、推测价格未来的变动方向的技术指标。
|
||||||
|
|
||||||
|
> RSI=[上升平均数÷(上升平均数+下跌平均数)]×100;
|
||||||
|
> 上升平均数是在某一段日子里升幅数的平均而下跌平均数则是在同一段日子里跌幅数的平均。
|
||||||
|
|
||||||
|
计算方法, 在lookback时间段内:
|
||||||
|
|
||||||
|
1. 计算magnitude of average of gains/losses over the period
|
||||||
|
|
||||||
|
$$AbsoluteGainOverPeriod = Price - PreviousPrice$$
|
||||||
|
|
||||||
|
$$AbsoluteLossOverPeriod = PreviousPrice - Price$$
|
||||||
|
|
||||||
|
$$RelativeStrength(RS) = \frac{\frac{\sum AbsoluteGainsOverLastNPeriods}{n}}{\frac{\sum AbsoluteLossesOverLastNPeriods}{n}}$$
|
||||||
|
|
||||||
|
可被简化为:
|
||||||
|
|
||||||
|
$$RelativeStrength(RS) = \frac{\sum AbsoluteGainsOverLastNPeriods}{\sum AbsoluteLossesOverLastNPeriods}$$
|
||||||
|
|
||||||
|
$$RelativeStrengthIndicator(RSI) = 100 - \frac{100}{(1+RS)}$$
|
||||||
|
|
||||||
|
![](sources/sec2/rsi.png)
|
||||||
|
|
||||||
|
* 上图使用了20天作为时间区域来计算上升平均数与下降平均数
|
||||||
|
* 上图说明了上升平均数基本上高于下降平均数,这与GOOG成功的股价直接相关
|
||||||
|
|
||||||
|
### 2.7 标准差 (STDEV)
|
||||||
|
|
||||||
|
**Standard deviation** = **STDEV**, 是金融资产价格波动性的体现,可被用于结合其他的指标。
|
||||||
|
|
||||||
|
计算方法:
|
||||||
|
|
||||||
|
1. 先计算 variance:
|
||||||
|
|
||||||
|
$$\sigma ^2 = \frac{\sum^n_{i=1}(P_i - SMA)^2}{n}$$
|
||||||
|
|
||||||
|
SMA = simple moving average over n time periods
|
||||||
|
|
||||||
|
2. 计算标准差:
|
||||||
|
|
||||||
|
$$\sigma = \sqrt{\sigma^2}$$
|
||||||
|
|
||||||
|
![](sources/sec2/stdev.png)
|
||||||
|
|
||||||
|
### 2.8 动量指标 (MOM)
|
||||||
|
|
||||||
|
MOM 为一个对价格移动的速度和量的衡量指标。可用作 trend/breakout-based trading algorithms.
|
||||||
|
|
||||||
|
$$MOM = Price_i - Price_{t-n}$$
|
||||||
|
|
||||||
|
* $Price_t$ 为在t时间的价格
|
||||||
|
* $Price_{t-n}$ 在t时间之前n个时间片段的价格
|
||||||
|
|
||||||
|
MOM的含义:
|
||||||
|
|
||||||
|
* 持续为正的MOM表示上升趋势
|
||||||
|
|
||||||
|
![](sources/sec2/momentum.png)
|
||||||
|
|
||||||
|
上图所示:
|
||||||
|
|
||||||
|
* MOM揭示了相比于20天前的股价,股价何时会有大幅变动
|
||||||
|
|
||||||
|
## 3. Implementing advanced concepts in trading instruments
|
||||||
|
|
||||||
|
### 3.1 季节性
|
||||||
|
|
||||||
|
金融产品价格会有季节性(周期性):每周,每月,每个假期, 例如下图
|
||||||
|
|
||||||
|
![](sources/sec2/seasonality.png)
|
||||||
|
|
||||||
|
* GOOG的从2001到2018的每月平均股价在10月有明显偏高
|
||||||
|
|
||||||
|
### 3.2 Time Series analysis
|
||||||
|
|
||||||
|
时间序列分析因为较为advanced,因此这里暂时略过
|
||||||
|
|
After Width: | Height: | Size: 66 KiB |
|
@ -0,0 +1,75 @@
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import statistics
|
||||||
|
from matplotlib.pyplot import legend, ylabel
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
from pandas_datareader import data
|
||||||
|
|
||||||
|
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
|
start_date = '2014-01-01'
|
||||||
|
end_date = '2018-01-01'
|
||||||
|
SRC_DATA_FILENAME = dir_path+'/goog_data.pkl'
|
||||||
|
|
||||||
|
try:
|
||||||
|
goog_data = pd.read_pickle(SRC_DATA_FILENAME)
|
||||||
|
print('File data found...reading GOOG data')
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('File not found...downloading the GOOG data')
|
||||||
|
goog_data = data.DataReader('GOOG', 'yahoo', start_date, end_date)
|
||||||
|
goog_data.to_pickle(SRC_DATA_FILENAME)
|
||||||
|
|
||||||
|
goog_data_signal = pd.DataFrame(index=goog_data.index)
|
||||||
|
goog_data_signal['price'] = goog_data['Adj Close']
|
||||||
|
close = goog_data_signal['price']
|
||||||
|
|
||||||
|
exe_start_time = time.time()
|
||||||
|
|
||||||
|
""" Calculate APO """
|
||||||
|
|
||||||
|
num_periods_fast = 10 # time period for the fast EMA
|
||||||
|
K_fast = 2/(num_periods_fast + 1)
|
||||||
|
ema_fast = 0
|
||||||
|
|
||||||
|
num_periods_slow = 40
|
||||||
|
K_slow = 2/(num_periods_slow + 1)
|
||||||
|
ema_slow = 0
|
||||||
|
|
||||||
|
ema_fast_values = [] # Hold fast EMA values for visualization purposes
|
||||||
|
ema_slow_values = [] # Hold slow EMA values for visualization purposes
|
||||||
|
apo_values = []
|
||||||
|
|
||||||
|
for close_price in close:
|
||||||
|
if (ema_fast == 0):
|
||||||
|
ema_fast = close_price
|
||||||
|
ema_slow = close_price
|
||||||
|
else:
|
||||||
|
ema_fast = (close_price - ema_fast) * K_fast + ema_fast
|
||||||
|
ema_slow = (close_price - ema_slow) * K_slow + ema_slow
|
||||||
|
|
||||||
|
ema_fast_values.append(ema_fast)
|
||||||
|
ema_slow_values.append(ema_slow)
|
||||||
|
apo_values.append(ema_fast - ema_slow)
|
||||||
|
|
||||||
|
""" Visualizing """
|
||||||
|
goog_data = goog_data.assign(ClosePrice=pd.Series(close, index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(FastExponential10DayMovingAverage=pd.Series(ema_fast_values, index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(SlowExponential140DayMovingAverage=pd.Series(ema_slow_values, index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(AbsolutePriceOscillator=pd.Series(apo_values, index=goog_data.index))
|
||||||
|
close_price = goog_data['ClosePrice']
|
||||||
|
ema_f = goog_data['FastExponential10DayMovingAverage']
|
||||||
|
ema_s = goog_data['SlowExponential140DayMovingAverage']
|
||||||
|
apo = goog_data['AbsolutePriceOscillator']
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
fig = plt.figure()
|
||||||
|
ax1 = fig.add_subplot(211, ylabel='Google price in $')
|
||||||
|
close_price.plot(ax=ax1, color='g', lw=2., legend=True)
|
||||||
|
ema_f.plot(ax=ax1, color='b', lw=2., legend=True)
|
||||||
|
ema_s.plot(ax=ax1, color='r', lw=2., legend=True)
|
||||||
|
ax2 = fig.add_subplot(212, ylabel='APO')
|
||||||
|
apo.plot(ax=ax2, color='black', lw=2., legend=True)
|
||||||
|
plt.savefig(dir_path + "/apo.png")
|
||||||
|
plt.show()
|
||||||
|
|
After Width: | Height: | Size: 68 KiB |
|
@ -0,0 +1,73 @@
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import statistics
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
from pandas_datareader import data
|
||||||
|
|
||||||
|
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
|
start_date = '2014-01-01'
|
||||||
|
end_date = '2018-01-01'
|
||||||
|
SRC_DATA_FILENAME = dir_path + '/goog_data.pkl'
|
||||||
|
|
||||||
|
try:
|
||||||
|
goog_data = pd.read_pickle(SRC_DATA_FILENAME)
|
||||||
|
print('File data found...reading GOOG data')
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('File not found...downloading the GOOG data')
|
||||||
|
goog_data = data.DataReader('GOOG', 'yahoo', start_date, end_date)
|
||||||
|
goog_data.to_pickle(SRC_DATA_FILENAME)
|
||||||
|
|
||||||
|
goog_data_signal = pd.DataFrame(index=goog_data.index)
|
||||||
|
goog_data_signal['price'] = goog_data['Adj Close']
|
||||||
|
close = goog_data_signal['price']
|
||||||
|
exe_start_time = time.time()
|
||||||
|
|
||||||
|
import statistics as stats
|
||||||
|
import math as math
|
||||||
|
|
||||||
|
time_period = 20 # history length for Simple Moving Average for middle band
|
||||||
|
stdev_factor = 2 # Standard Deviation Scaling factor for the upper and lower bands
|
||||||
|
|
||||||
|
history = []
|
||||||
|
sma_values = []
|
||||||
|
upper_band = []
|
||||||
|
lower_band = []
|
||||||
|
|
||||||
|
""" Calculate BBAND """
|
||||||
|
|
||||||
|
for close_price in close:
|
||||||
|
history.append(close_price)
|
||||||
|
if len(history) > time_period:
|
||||||
|
del(history[0])
|
||||||
|
|
||||||
|
sma = stats.mean(history) # BBAND_Middle
|
||||||
|
sma_values.append(sma)
|
||||||
|
|
||||||
|
variance = 0
|
||||||
|
|
||||||
|
# Calculate variance using pure python
|
||||||
|
for hist_price in history:
|
||||||
|
variance = variance + ((hist_price - sma) ** 2)
|
||||||
|
|
||||||
|
stdev = math.sqrt(variance / len(history))
|
||||||
|
upper_band.append(sma + stdev_factor * stdev)
|
||||||
|
lower_band.append(sma - stdev_factor * stdev)
|
||||||
|
|
||||||
|
""" Draw Gragh """
|
||||||
|
goog_data = goog_data.assign(ClosePrice=pd.Series(close, index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(MiddleBollingerBand20DaySMA=pd.Series(sma_values, index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(UpperBollingerBand20DaysSMA2StddevFactor=pd.Series(upper_band, index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(LowerBollingerBand20DaysSMA2StddevFactor=pd.Series(lower_band, index=goog_data.index))
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
fig = plt.figure()
|
||||||
|
ax1 = fig.add_subplot(111, ylabel='Google price in $')
|
||||||
|
goog_data['ClosePrice'].plot(ax=ax1, color='g', lw=2., legend=True)
|
||||||
|
goog_data['MiddleBollingerBand20DaySMA'].plot(ax=ax1, color='b', lw=2., legend=True)
|
||||||
|
goog_data['UpperBollingerBand20DaysSMA2StddevFactor'].plot(ax=ax1, color='y', lw=2., legend=True)
|
||||||
|
goog_data['LowerBollingerBand20DaysSMA2StddevFactor'].plot(ax=ax1, color='r', lw=2., legend=True)
|
||||||
|
plt.savefig(dir_path + '/bbands.png')
|
||||||
|
plt.show()
|
After Width: | Height: | Size: 45 KiB |
|
@ -0,0 +1,58 @@
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import statistics
|
||||||
|
from matplotlib.pyplot import ylabel
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
from pandas_datareader import data
|
||||||
|
|
||||||
|
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
|
start_date = '2014-01-01'
|
||||||
|
end_date = '2018-01-01'
|
||||||
|
SRC_DATA_FILENAME = dir_path + '/goog_data.pkl'
|
||||||
|
|
||||||
|
try:
|
||||||
|
goog_data = pd.read_pickle(SRC_DATA_FILENAME)
|
||||||
|
print('File data found...reading GOOG data')
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('File not found...downloading the GOOG data')
|
||||||
|
goog_data = data.DataReader('GOOG', 'yahoo', start_date, end_date)
|
||||||
|
goog_data.to_pickle(SRC_DATA_FILENAME)
|
||||||
|
|
||||||
|
goog_data_signal = pd.DataFrame(index=goog_data.index)
|
||||||
|
goog_data_signal['price'] = goog_data['Adj Close']
|
||||||
|
close = goog_data_signal['price']
|
||||||
|
|
||||||
|
exe_start_time = time.time()
|
||||||
|
|
||||||
|
""" Calculate EMA """
|
||||||
|
|
||||||
|
num_periods = 20 # number of days over which to average
|
||||||
|
K = 2/(num_periods + 1) # smoothing constant
|
||||||
|
ema_p = 0
|
||||||
|
ema_values = []
|
||||||
|
|
||||||
|
for close_price in close:
|
||||||
|
if (ema_p == 0):
|
||||||
|
# first observation, EMA = current price
|
||||||
|
ema_p = close_price
|
||||||
|
else:
|
||||||
|
ema_p = (close_price - ema_p) * K + ema_p
|
||||||
|
|
||||||
|
ema_values.append(ema_p)
|
||||||
|
|
||||||
|
goog_data = goog_data.assign(ClosePrice=pd.Series(close, index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(Exponential120DayMovingAverage=pd.Series(ema_values, index=goog_data.index))
|
||||||
|
close_price = goog_data['ClosePrice']
|
||||||
|
ema = goog_data['Exponential120DayMovingAverage']
|
||||||
|
|
||||||
|
""" Draw plot """
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
fig = plt.figure()
|
||||||
|
ax1 = fig.add_subplot(111, ylabel='Google price in $')
|
||||||
|
close_price.plot(ax=ax1, color='g', lw=2., legend=True)
|
||||||
|
ema.plot(ax=ax1, color='b', lw=2., legend=True)
|
||||||
|
plt.savefig(dir_path + '/ema.png')
|
||||||
|
plt.show()
|
After Width: | Height: | Size: 66 KiB |
|
@ -0,0 +1,97 @@
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import statistics
|
||||||
|
from matplotlib.pyplot import legend, ylabel
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
from pandas_datareader import data
|
||||||
|
|
||||||
|
|
||||||
|
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
|
start_date = '2014-01-01'
|
||||||
|
end_date = '2018-01-01'
|
||||||
|
SRC_DATA_FILENAME = dir_path + '/goog_data.pkl'
|
||||||
|
|
||||||
|
try:
|
||||||
|
goog_data = pd.read_pickle(SRC_DATA_FILENAME)
|
||||||
|
print('File data found...reading GOOG data')
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('File not found...downloading the GOOG data')
|
||||||
|
goog_data = data.DataReader('GOOG', 'yahoo', start_date, end_date)
|
||||||
|
goog_data.to_pickle(SRC_DATA_FILENAME)
|
||||||
|
|
||||||
|
goog_data_signal = pd.DataFrame(index=goog_data.index)
|
||||||
|
goog_data_signal['price'] = goog_data['Adj Close']
|
||||||
|
close = goog_data_signal['price']
|
||||||
|
|
||||||
|
exe_start_time = time.time()
|
||||||
|
|
||||||
|
""" Calculate MACD """
|
||||||
|
|
||||||
|
num_periods_fast = 10 # fast EMA time period
|
||||||
|
K_fast = 2/(num_periods_fast+1)
|
||||||
|
ema_fast = 0
|
||||||
|
|
||||||
|
num_periods_slow = 40 # slow EMA time period
|
||||||
|
K_slow = 2/(num_periods_slow+1)
|
||||||
|
ema_slow = 0
|
||||||
|
|
||||||
|
num_periods_macd = 20 # MACD EMA time period
|
||||||
|
K_macd = 2/(num_periods_macd+1)
|
||||||
|
ema_macd=0
|
||||||
|
|
||||||
|
ema_fast_values = []
|
||||||
|
ema_slow_values = []
|
||||||
|
macd_values = []
|
||||||
|
macd_signal_values = []
|
||||||
|
|
||||||
|
macd_histogram_values = []
|
||||||
|
|
||||||
|
for close_price in close:
|
||||||
|
if (ema_fast == 0):
|
||||||
|
ema_fast = close_price
|
||||||
|
ema_slow = close_price
|
||||||
|
else:
|
||||||
|
ema_fast = (close_price - ema_fast) * K_fast + ema_fast
|
||||||
|
ema_slow = (close_price - ema_slow) * K_slow + ema_slow
|
||||||
|
|
||||||
|
ema_fast_values.append(ema_fast)
|
||||||
|
ema_slow_values.append(ema_slow)
|
||||||
|
macd = ema_fast - ema_slow # calculate MACD
|
||||||
|
|
||||||
|
# Based on APO(MACD), calculate EMA_MACD
|
||||||
|
if ema_macd == 0:
|
||||||
|
ema_macd = macd
|
||||||
|
else:
|
||||||
|
ema_macd = (macd - ema_macd) * K_slow + ema_macd
|
||||||
|
macd_values.append(macd)
|
||||||
|
|
||||||
|
macd_signal_values.append(ema_macd)
|
||||||
|
macd_histogram_values.append(macd - ema_macd)
|
||||||
|
|
||||||
|
""" Visualization """
|
||||||
|
# assign data back to goog_data to get index and aligned
|
||||||
|
goog_data = goog_data.assign(ClosePrice=pd.Series(close, index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(Fast_EMA_110Days=pd.Series(ema_fast_values, index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(Slow_EMA_140Days=pd.Series(ema_slow_values, index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(MACD=pd.Series(macd_values, index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(EMA_of_MACD_120Days=pd.Series(macd_signal_values, index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(MACDHistogram=pd.Series(macd_histogram_values, index=goog_data.index))
|
||||||
|
print(goog_data['MACDHistogram'])
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
fig = plt.figure()
|
||||||
|
ax1 = fig.add_subplot(311, ylabel='Google price in $')
|
||||||
|
goog_data['ClosePrice'].plot(ax=ax1, color='g', lw=2., legend=True)
|
||||||
|
goog_data['Fast_EMA_110Days'].plot(ax=ax1, color='b', lw=2., legend=True)
|
||||||
|
goog_data['Slow_EMA_140Days'].plot(ax=ax1, color='r', lw=2., legend=True)
|
||||||
|
ax2 = fig.add_subplot(312, ylabel='MACD')
|
||||||
|
goog_data['MACD'].plot(ax=ax2, color='black', lw=2., legend=True)
|
||||||
|
goog_data['EMA_of_MACD_120Days'].plot(ax=ax2, color='g', lw=2., legend=True)
|
||||||
|
ax3 = fig.add_subplot(313, ylabel='MACD')
|
||||||
|
goog_data['MACDHistogram'].plot(ax=ax3, color='r', kind='bar', legend=True, use_index=False)
|
||||||
|
|
||||||
|
plt.savefig(dir_path + "/macd.png")
|
||||||
|
plt.show()
|
After Width: | Height: | Size: 54 KiB |
|
@ -0,0 +1,54 @@
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import statistics
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
from pandas_datareader import data
|
||||||
|
|
||||||
|
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
|
start_date = '2014-01-01'
|
||||||
|
end_date = '2018-01-01'
|
||||||
|
SRC_DATA_FILENAME = dir_path + '/goog_data.pkl'
|
||||||
|
|
||||||
|
try:
|
||||||
|
goog_data = pd.read_pickle(SRC_DATA_FILENAME)
|
||||||
|
print('File data found...reading GOOG data')
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('File not found...downloading the GOOG data')
|
||||||
|
goog_data = data.DataReader('GOOG', 'yahoo', start_date, end_date)
|
||||||
|
goog_data.to_pickle(SRC_DATA_FILENAME)
|
||||||
|
|
||||||
|
goog_data_signal = pd.DataFrame(index=goog_data.index)
|
||||||
|
goog_data_signal['price'] = goog_data['Adj Close']
|
||||||
|
close = goog_data_signal['price']
|
||||||
|
exe_start_time = time.time()
|
||||||
|
|
||||||
|
""" Calculate momentum """
|
||||||
|
|
||||||
|
time_period = 20 # lookback period
|
||||||
|
history = [] # history of observed prices to use in momentum calculation
|
||||||
|
mom_values = [] # track momentum values for visualization purposes
|
||||||
|
|
||||||
|
for close_price in close:
|
||||||
|
history.append(close_price)
|
||||||
|
if len(history) > time_period:
|
||||||
|
del(history[0])
|
||||||
|
|
||||||
|
mom = close_price - history[0]
|
||||||
|
mom_values.append(mom)
|
||||||
|
|
||||||
|
goog_data = goog_data.assign(ClosePrice=pd.Series(close, index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(MomentumFromPrice20DaysAgo=pd.Series(mom_values, index=goog_data.index))
|
||||||
|
|
||||||
|
""" Visualization """
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
fig = plt.figure()
|
||||||
|
ax1 = fig.add_subplot(211, ylabel='Google price in $')
|
||||||
|
goog_data['ClosePrice'].plot(ax=ax1, color='g', lw=2., legend=True)
|
||||||
|
ax2 = fig.add_subplot(212, ylabel='Momentum in $')
|
||||||
|
goog_data['MomentumFromPrice20DaysAgo'].plot(ax=ax2, color='b', lw=2., legend=True)
|
||||||
|
plt.savefig(dir_path + '/momentum.png')
|
||||||
|
plt.show()
|
After Width: | Height: | Size: 75 KiB |
|
@ -0,0 +1,81 @@
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import statistics
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
from pandas_datareader import data
|
||||||
|
|
||||||
|
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
|
start_date = '2014-01-01'
|
||||||
|
end_date = '2018-01-01'
|
||||||
|
SRC_DATA_FILENAME = dir_path + '/goog_data.pkl'
|
||||||
|
|
||||||
|
try:
|
||||||
|
goog_data = pd.read_pickle(SRC_DATA_FILENAME)
|
||||||
|
print('File data found...reading GOOG data')
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('File not found...downloading the GOOG data')
|
||||||
|
goog_data = data.DataReader('GOOG', 'yahoo', start_date, end_date)
|
||||||
|
goog_data.to_pickle(SRC_DATA_FILENAME)
|
||||||
|
|
||||||
|
goog_data_signal = pd.DataFrame(index=goog_data.index)
|
||||||
|
goog_data_signal['price'] = goog_data['Adj Close']
|
||||||
|
close = goog_data_signal['price']
|
||||||
|
exe_start_time = time.time()
|
||||||
|
|
||||||
|
import statistics as stats
|
||||||
|
|
||||||
|
time_period = 20 # look back period to compute gains & losses
|
||||||
|
|
||||||
|
gain_history = [] # history of gains over look back period (0 if no gain, magnitude of gain if gain)
|
||||||
|
loss_history = [] # history of losses over look back period (0 if no loss, magnitude of loss if loss)
|
||||||
|
avg_gain_values = [] # track avg gains for visualization purposes
|
||||||
|
avg_loss_values = []
|
||||||
|
|
||||||
|
rsi_values = [] # track computed RSI values
|
||||||
|
|
||||||
|
last_price = 0 # current_price - last_price > 0 => gain ; current_price - last_price < 0 => loss.
|
||||||
|
|
||||||
|
for close_price in close:
|
||||||
|
if last_price == 0:
|
||||||
|
last_price = close_price
|
||||||
|
|
||||||
|
gain_history.append(max(0, close_price - last_price))
|
||||||
|
loss_history.append(max(0, last_price - close_price))
|
||||||
|
last_price = close_price
|
||||||
|
|
||||||
|
if len(gain_history) > time_period:
|
||||||
|
del(gain_history[0])
|
||||||
|
del(loss_history[0])
|
||||||
|
|
||||||
|
avg_gain = stats.mean(gain_history) # average gain over lookback period
|
||||||
|
avg_loss = stats.mean(loss_history) # average loss over lookback period
|
||||||
|
avg_gain_values.append(avg_gain)
|
||||||
|
avg_loss_values.append(avg_loss)
|
||||||
|
|
||||||
|
rs = 0
|
||||||
|
if avg_loss > 0: # to avoid division by 0, which is undefined
|
||||||
|
rs = avg_gain /avg_loss
|
||||||
|
rsi = 100 - (100/(1+rs))
|
||||||
|
rsi_values.append(rsi)
|
||||||
|
|
||||||
|
""" Data Visualization """
|
||||||
|
|
||||||
|
goog_data = goog_data.assign(ClosePrice=pd.Series(close,index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(RelativeStrengthAvgGainOver20Days=pd.Series(avg_gain_values, index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(RelativeStrengthAvgLossOver20Days=pd.Series(avg_loss_values, index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(RelativeStrengthIndicatorOver20Days=pd.Series(rsi_values, index=goog_data.index))
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
fig = plt.figure()
|
||||||
|
ax1 = fig.add_subplot(311, ylabel='Google price in $')
|
||||||
|
goog_data['ClosePrice'].plot(ax=ax1, color='black', lw=2., legend=True)
|
||||||
|
ax2 = fig.add_subplot(312, ylabel='RS')
|
||||||
|
goog_data['RelativeStrengthAvgGainOver20Days'].plot(ax=ax2, color='g', lw=2., legend=True)
|
||||||
|
goog_data['RelativeStrengthAvgLossOver20Days'].plot(ax=ax2, color='r', lw=2., legend=True)
|
||||||
|
ax3 = fig.add_subplot(313, ylabel='RSI')
|
||||||
|
goog_data['RelativeStrengthIndicatorOver20Days'].plot(ax=ax3, color='b', lw=2., legend=True)
|
||||||
|
plt.savefig(dir_path + '/rsi.png')
|
||||||
|
plt.show()
|
After Width: | Height: | Size: 25 KiB |
|
@ -0,0 +1,58 @@
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import statistics
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
from pandas_datareader import data
|
||||||
|
|
||||||
|
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
|
start_date = '2001-01-01'
|
||||||
|
end_date = '2018-01-01'
|
||||||
|
SRC_DATA_FILENAME = dir_path + '/goog_data_large.pkl'
|
||||||
|
|
||||||
|
try:
|
||||||
|
goog_data = pd.read_pickle(SRC_DATA_FILENAME)
|
||||||
|
print('File data found...reading GOOG data')
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('File not found...downloading the GOOG data')
|
||||||
|
goog_data = data.DataReader('GOOG', 'yahoo', start_date, end_date)
|
||||||
|
goog_data.to_pickle(SRC_DATA_FILENAME)
|
||||||
|
|
||||||
|
goog_data_signal = pd.DataFrame(index=goog_data.index)
|
||||||
|
goog_data_signal['price'] = goog_data['Adj Close']
|
||||||
|
close = goog_data_signal['price']
|
||||||
|
exe_start_time = time.time()
|
||||||
|
|
||||||
|
""" Calculate mean of each month's return """
|
||||||
|
|
||||||
|
goog_monthly_return = goog_data['Adj Close'].pct_change().groupby(
|
||||||
|
[goog_data['Adj Close'].index.year, goog_data['Adj Close'].index.month]).mean()
|
||||||
|
print(goog_monthly_return)
|
||||||
|
|
||||||
|
goog_monthly_return_list = []
|
||||||
|
|
||||||
|
for i in range(len(goog_monthly_return)):
|
||||||
|
goog_monthly_return_list.append({'month':goog_monthly_return.index[i][1],'monthly_return': goog_monthly_return[i]})
|
||||||
|
|
||||||
|
goog_monthly_return_list=pd.DataFrame(goog_monthly_return_list,\
|
||||||
|
columns=('month','monthly_return'))
|
||||||
|
print(goog_monthly_return_list)
|
||||||
|
|
||||||
|
goog_monthly_return_list.boxplot(column='monthly_return', by='month')
|
||||||
|
|
||||||
|
""" Visulization """
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
ax = plt.gca()
|
||||||
|
labels = [item.get_text() for item in ax.get_xticklabels()]
|
||||||
|
print(labels)
|
||||||
|
labels = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
|
||||||
|
ax.set_xticklabels(labels)
|
||||||
|
ax.set_ylabel('GOOG return')
|
||||||
|
plt.tick_params(axis='both', which='major', labelsize=7)
|
||||||
|
plt.title("GOOG Monthly return 2001-2018")
|
||||||
|
plt.suptitle("")
|
||||||
|
plt.savefig(dir_path + '/seasonality.png')
|
||||||
|
plt.show()
|
After Width: | Height: | Size: 52 KiB |
|
@ -0,0 +1,64 @@
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import statistics
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
from pandas_datareader import data
|
||||||
|
|
||||||
|
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
|
start_date = '2014-01-01'
|
||||||
|
end_date = '2018-01-01'
|
||||||
|
SRC_DATA_FILENAME = 'goog_data.pkl'
|
||||||
|
|
||||||
|
try:
|
||||||
|
goog_data = pd.read_pickle(SRC_DATA_FILENAME)
|
||||||
|
print('File data found...reading GOOG data')
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('File not found...downloading the GOOG data')
|
||||||
|
goog_data = data.DataReader('GOOG', 'yahoo', start_date, end_date)
|
||||||
|
goog_data.to_pickle(SRC_DATA_FILENAME)
|
||||||
|
|
||||||
|
goog_data_signal = pd.DataFrame(index=goog_data.index)
|
||||||
|
goog_data_signal['price'] = goog_data['Adj Close']
|
||||||
|
|
||||||
|
exe_start_time = time.time()
|
||||||
|
|
||||||
|
import statistics as stats
|
||||||
|
|
||||||
|
time_period = 20 # number of days over which to average
|
||||||
|
history = [] # to track a history of prices
|
||||||
|
sma_values = [] # to track simple moving average values
|
||||||
|
|
||||||
|
for close_price in goog_data_signal['price']:
|
||||||
|
history.append(close_price)
|
||||||
|
if len(history) > time_period:
|
||||||
|
# we remove oldest price because we only average over last 'time_period' prices
|
||||||
|
# i.e. keep the latest 20 day window
|
||||||
|
del(history[0])
|
||||||
|
sma_values.append(stats.mean(history))
|
||||||
|
# The first 20 sma of this data will not be mean of 20 values
|
||||||
|
|
||||||
|
print("--- algo1: %s seconds ---" % (time.time() - exe_start_time))
|
||||||
|
|
||||||
|
exe_start_time = time.time()
|
||||||
|
|
||||||
|
sma_values_improved = goog_data_signal.rolling(window=20, win_type='boxcar').mean()
|
||||||
|
|
||||||
|
print("--- algo2: %s seconds ---" % (time.time() - exe_start_time))
|
||||||
|
|
||||||
|
goog_data = goog_data.assign(ClosePrice=pd.Series(goog_data_signal['price'], index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(Simple20DayMovingAverage=pd.Series(sma_values, index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(Simple20DayMovingAverage_pd = sma_values_improved)
|
||||||
|
close_price = goog_data['ClosePrice']
|
||||||
|
sma = goog_data['Simple20DayMovingAverage']
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
fig = plt.figure()
|
||||||
|
ax1 = fig.add_subplot(111, ylabel='Google price in $')
|
||||||
|
close_price.plot(ax=ax1, color='g', lw=2., legend=True)
|
||||||
|
sma.plot(ax=ax1, color='r', lw=2., legend=True)
|
||||||
|
goog_data['Simple20DayMovingAverage_pd'].plot(ax=ax1, color='b', lw=1., legend=True)
|
||||||
|
plt.savefig(dir_path+'/sma.png')
|
||||||
|
plt.show()
|
|
@ -0,0 +1,58 @@
|
||||||
|
# Same method as in sma.py, used pandas.DataFrame.rolling for faster calculation
|
||||||
|
|
||||||
|
import time
|
||||||
|
import statistics
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
from pandas_datareader import data
|
||||||
|
|
||||||
|
exe_start_time = time.time()
|
||||||
|
|
||||||
|
start_date = '2014-01-01'
|
||||||
|
end_date = '2018-01-01'
|
||||||
|
SRC_DATA_FILENAME = 'goog_data.pkl'
|
||||||
|
|
||||||
|
try:
|
||||||
|
goog_data = pd.read_pickle(SRC_DATA_FILENAME)
|
||||||
|
print('File data found...reading GOOG data')
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('File not found...downloading the GOOG data')
|
||||||
|
goog_data = data.DataReader('GOOG', 'yahoo', start_date, end_date)
|
||||||
|
goog_data.to_pickle(SRC_DATA_FILENAME)
|
||||||
|
|
||||||
|
goog_data_signal = pd.DataFrame(index=goog_data.index)
|
||||||
|
goog_data_signal['price'] = goog_data['Adj Close']
|
||||||
|
|
||||||
|
import statistics as stats
|
||||||
|
|
||||||
|
time_period = 20 # number of days over which to average
|
||||||
|
history = [] # to track a history of prices
|
||||||
|
sma_values = [] # to track simple moving average values
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
goog_data = goog_data.assign(ClosePrice=pd.Series(close, index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(Simple20DayMovinigAverage=pd.Series(result, index=goog_data.index))
|
||||||
|
print(result)
|
||||||
|
|
||||||
|
|
||||||
|
# for close_price in close:
|
||||||
|
# history.append(close_price)
|
||||||
|
# if len(history) > time_period: # we remove oldest price because we only average over last 'time_period' prices
|
||||||
|
# del(history[0])
|
||||||
|
# sma_values.append(stats.mean(history))
|
||||||
|
|
||||||
|
# goog_data = goog_data.assign(ClosePrice=pd.Series(close, index=goog_data.index))
|
||||||
|
# goog_data = goog_data.assign(Simple20DayMovingAverage=pd.Series(sma_values, index=goog_data.index))
|
||||||
|
# close_price = goog_data['ClosePrice']
|
||||||
|
# sma = goog_data['Simple20DayMovingAverage']
|
||||||
|
|
||||||
|
# print("--- %s seconds ---" % (time.time() - exe_start_time))
|
||||||
|
|
||||||
|
# import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
# fig = plt.figure()
|
||||||
|
# ax1 = fig.add_subplot(111, ylabel='Google price in $')
|
||||||
|
# close_price.plot(ax=ax1, color='g', lw=2., legend=True)
|
||||||
|
# sma.plot(ax=ax1, color='r', lw=2., legend=True)
|
||||||
|
# plt.savefig('sma.png')
|
After Width: | Height: | Size: 51 KiB |
|
@ -0,0 +1,65 @@
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import statistics
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
from pandas_datareader import data
|
||||||
|
|
||||||
|
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
|
start_date = '2014-01-01'
|
||||||
|
end_date = '2018-01-01'
|
||||||
|
SRC_DATA_FILENAME = 'goog_data.pkl'
|
||||||
|
|
||||||
|
try:
|
||||||
|
goog_data = pd.read_pickle(SRC_DATA_FILENAME)
|
||||||
|
print('File data found...reading GOOG data')
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('File not found...downloading the GOOG data')
|
||||||
|
goog_data = data.DataReader('GOOG', 'yahoo', start_date, end_date)
|
||||||
|
goog_data.to_pickle(SRC_DATA_FILENAME)
|
||||||
|
|
||||||
|
goog_data_signal = pd.DataFrame(index=goog_data.index)
|
||||||
|
goog_data_signal['price'] = goog_data['Adj Close']
|
||||||
|
close = goog_data_signal['price']
|
||||||
|
exe_start_time = time.time()
|
||||||
|
|
||||||
|
import statistics as stats
|
||||||
|
import math as math
|
||||||
|
|
||||||
|
time_period = 20
|
||||||
|
|
||||||
|
history = [] # history of prices
|
||||||
|
sma_values = [] # to tracking sma
|
||||||
|
stddev_values = [] # history of computed stdev values
|
||||||
|
|
||||||
|
for close_price in close:
|
||||||
|
history.append(close_price)
|
||||||
|
if len(history) > time_period: # track at most 20 prices
|
||||||
|
del(history[0])
|
||||||
|
|
||||||
|
sma = stats.mean(history)
|
||||||
|
sma_values.append(sma)
|
||||||
|
|
||||||
|
variance = 0
|
||||||
|
for hist_price in history:
|
||||||
|
variance = variance + ((hist_price - sma) ** 2)
|
||||||
|
|
||||||
|
stdev = math.sqrt(variance / len(history))
|
||||||
|
stddev_values.append(stdev)
|
||||||
|
|
||||||
|
|
||||||
|
goog_data = goog_data.assign(ClosePrice=pd.Series(close, index=goog_data.index))
|
||||||
|
goog_data = goog_data.assign(StandardDeviationOver20Days=pd.Series(stddev_values, index=goog_data.index))
|
||||||
|
|
||||||
|
""" Visualization """
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
fig = plt.figure()
|
||||||
|
ax1 = fig.add_subplot(211, ylabel='Google price in $')
|
||||||
|
goog_data['ClosePrice'].plot(ax=ax1, color='g', lw=2., legend=True)
|
||||||
|
ax2 = fig.add_subplot(212, ylabel='Stddev in $')
|
||||||
|
goog_data['StandardDeviationOver20Days'].plot(ax=ax2, color='b', lw=2., legend=True)
|
||||||
|
plt.savefig(dir_path + '/stdev.png')
|
||||||
|
plt.show()
|
After Width: | Height: | Size: 42 KiB |
|
@ -0,0 +1,29 @@
|
||||||
|
import pandas as pd
|
||||||
|
from pandas_datareader import data
|
||||||
|
|
||||||
|
start_date = '2014-01-01'
|
||||||
|
end_date = '2018-01-01'
|
||||||
|
SRC_DATA_FILENAME = 'goog_data.pkl'
|
||||||
|
|
||||||
|
try:
|
||||||
|
goog_data2 = pd.read_pickle(SRC_DATA_FILENAME)
|
||||||
|
except FileNotFoundError:
|
||||||
|
goog_data2 = data.DataReader('GOOG', 'yahoo', start_date, end_date)
|
||||||
|
goog_data2.to_pickle(SRC_DATA_FILENAME)
|
||||||
|
|
||||||
|
goog_data = goog_data2.tail(620)
|
||||||
|
lows = goog_data['Low']
|
||||||
|
highs = goog_data['High']
|
||||||
|
print(goog_data)
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
fig = plt.figure()
|
||||||
|
ax1 = fig.add_subplot(111, ylabel='Google price in $')
|
||||||
|
highs.plot(ax=ax1, color='c', lw=2.)
|
||||||
|
lows.plot(ax=ax1, color='y', lw=2.)
|
||||||
|
|
||||||
|
# Return the first 200 rows using pandas.DataFrame.head(200)
|
||||||
|
plt.hlines(highs.head(200).max(), lows.index.values[0], lows.index.values[-1], linewidth=2, color='g')
|
||||||
|
plt.hlines(lows.head(200).min(), lows.index.values[0], lows.index.values[-1], linewidth=2, color='r')
|
||||||
|
plt.axvline(linewidth=2, color='b', x=lows.index.values[200], linestyle=':')
|
||||||
|
plt.savefig("supportresistanceline.png")
|
After Width: | Height: | Size: 45 KiB |
|
@ -0,0 +1,94 @@
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
from pandas_datareader import data
|
||||||
|
|
||||||
|
start_date = '2014-01-01'
|
||||||
|
end_date = '2018-01-01'
|
||||||
|
SRC_DATA_FILENAME = 'goog_data.pkl'
|
||||||
|
|
||||||
|
try:
|
||||||
|
goog_data = pd.read_pickle(SRC_DATA_FILENAME)
|
||||||
|
print('File data found...reading GOOG data')
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('File not found...downloading the GOOG data')
|
||||||
|
goog_data = data.DataReader('GOOG', 'yahoo', start_date, end_date)
|
||||||
|
goog_data.to_pickle(SRC_DATA_FILENAME)
|
||||||
|
|
||||||
|
goog_data_signal = pd.DataFrame(index=goog_data.index)
|
||||||
|
goog_data_signal['price'] = goog_data['Adj Close']
|
||||||
|
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
def trading_support_resistance(data, bin_width=20):
|
||||||
|
|
||||||
|
data['sup_tolerance'] = pd.Series(np.zeros(len(data))) # tolerance of support line
|
||||||
|
data['res_tolerance'] = pd.Series(np.zeros(len(data))) # tolerance of resistance line
|
||||||
|
|
||||||
|
data['sup_count'] = pd.Series(np.zeros(len(data))) # number of hitting support line
|
||||||
|
data['res_count'] = pd.Series(np.zeros(len(data)))
|
||||||
|
|
||||||
|
data['sup'] = pd.Series(np.zeros(len(data))) # support line value (constant)
|
||||||
|
data['res'] = pd.Series(np.zeros(len(data)))
|
||||||
|
|
||||||
|
data['position'] = pd.Series(np.zeros(len(data)))
|
||||||
|
data['signal'] = pd.Series(np.zeros(len(data)))
|
||||||
|
|
||||||
|
in_support = 0
|
||||||
|
in_resistance = 0
|
||||||
|
|
||||||
|
for x in range((bin_width-1) + bin_width, len(data)):
|
||||||
|
data_section = data[x-bin_width : x+1] # get data within rolling window
|
||||||
|
|
||||||
|
support_level = min(data_section['price'])
|
||||||
|
resistance_level = max(data_section['price'])
|
||||||
|
range_level = resistance_level - support_level
|
||||||
|
|
||||||
|
data['res'][x] = resistance_level
|
||||||
|
data['sup'][x] = support_level
|
||||||
|
|
||||||
|
data['sup_tolerance'][x] = support_level + 0.2*range_level # 20% tolorance
|
||||||
|
data['res_tolerance'][x] = resistance_level - 0.2*range_level
|
||||||
|
|
||||||
|
if (data['price'][x] >= data['res_tolerance'][x]) and (data['price'][x] <= data['res'][x]):
|
||||||
|
# if price is within resistance tolerance region
|
||||||
|
in_resistance += 1
|
||||||
|
data['res_count'][x] = in_resistance
|
||||||
|
elif (data['price'][x] <= data['sup_tolerance'][x]) and (data['price'][x] >= data['sup'][x]):
|
||||||
|
# price is within support tolerance region
|
||||||
|
in_support += 1
|
||||||
|
data['sup_count'][x] = in_support
|
||||||
|
else:
|
||||||
|
# if not within any region, clear count
|
||||||
|
in_support = 0
|
||||||
|
in_resistance = 0
|
||||||
|
|
||||||
|
if in_resistance > 2:
|
||||||
|
# If enter resistance region twice
|
||||||
|
data['signal'][x] = 1
|
||||||
|
elif in_support > 2:
|
||||||
|
data['signal'][x] = 0
|
||||||
|
else:
|
||||||
|
data['signal'][x] = data['signal'][x-1]
|
||||||
|
|
||||||
|
data['position'] = data['signal'].diff()
|
||||||
|
|
||||||
|
trading_support_resistance(goog_data_signal)
|
||||||
|
|
||||||
|
print(goog_data_signal)
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
fig = plt.figure()
|
||||||
|
ax1 = fig.add_subplot(111, ylabel='Google price in $')
|
||||||
|
goog_data_signal['sup'].plot(ax=ax1, color='g', lw=2.)
|
||||||
|
goog_data_signal['res'].plot(ax=ax1, color='b', lw=2.)
|
||||||
|
goog_data_signal['price'].plot(ax=ax1, color='r', lw=2.)
|
||||||
|
|
||||||
|
ax1.plot(goog_data_signal.loc[goog_data_signal.position == 1.0].index,
|
||||||
|
goog_data_signal.price[goog_data_signal.position == 1.0], '^', markersize=7, color='k', label='buy')
|
||||||
|
ax1.plot(goog_data_signal.loc[goog_data_signal.position == -1.0].index,
|
||||||
|
goog_data_signal.price[goog_data_signal.position == -1.0], 'v', markersize=7, color='k', label='sell')
|
||||||
|
|
||||||
|
plt.legend()
|
||||||
|
plt.savefig("supportresistanceline_improved")
|
||||||
|
plt.show()
|
After Width: | Height: | Size: 57 KiB |