针对股票涨跌信息的一系列处理
針對股票漲跌信息的一系列處理
- 線性模型
- 線性預測
- 線性擬合
- 協方差
- 相關系數
- 相關矩陣
- 多項式擬合
- 數據平滑
- 符號數組
- 矢量化
線性模型
什么是線性關系?
x = 1 → y = 60 x = 2 → y = 65 x = 3 → y = 70 x = 4 → y = 75 x = 5 → y = ? ? ? x=1 \quad \rarr \quad y=60 \\ x=2 \quad \rarr \quad y=65 \\ x=3 \quad \rarr \quad y=70 \\ x=4 \quad \rarr \quad y=75 \\ x=5 \quad \rarr \quad y= ??? \\ x=1→y=60x=2→y=65x=3→y=70x=4→y=75x=5→y=???
線性預測
假設一組數據符合一種線型規律,那么就可以預測未來將會出現的數據。
a b c d e f ? a b c d e f g h ?{ a w 0 + b w 1 + c w 2 = d b w 0 + c w 1 + d w 2 = e c w 0 + d w 1 + e w 2 = f \begin{cases} aw_0 + bw_1 + cw_2 = d \\ bw_0 + cw_1 + dw_2 = e \\ cw_0 + dw_1 + ew_2 = f \\ \end{cases} ??????aw0?+bw1?+cw2?=dbw0?+cw1?+dw2?=ecw0?+dw1?+ew2?=f?
線型方程組轉換為矩陣相乘的形式:
[ a b c b c d c d e ] × [ w 0 w 1 w 2 ] = [ d e f ] A x B \left[ \begin{array}{ccc} a & b & c\\ b & c & d\\ c & d & e\\ \end{array} \right ] \times \left[ \begin{array}{ccc} w_0\\ w_1\\ w_2\\ \end{array} \right ]= \left[ \begin{array}{ccc} d\\ e\\ f\\ \end{array} \right ] \\ \quad \quad A \quad \quad \quad \quad \quad x\quad \quad \quad B \quad ???abc?bcd?cde????×???w0?w1?w2?????=???def????AxB
根據線性模型的特點可以通過一組歷史數據求出線性關系系數x, y, z,從而預測d、e、f下的一個數據是多少。
線性預測需要使用歷史數據進行檢驗,讓預測結果可信度更高
案例:使用線性預測,預測下一天的收盤價。
import numpy as np import matplotlib.pyplot as mp import datetime as dtdef dmy2ymd(dmy):dmy = str(dmy, encoding='utf-8')time = dt.datetime.strptime(dmy, '%d-%m-%Y').date()t = time.strftime('%Y-%m-%d')return tdates, opening_prices, highest_prices, \lowest_prices, closing_prices = \np.loadtxt('C:/Users/ADMIN/Desktop/DATASCIENCE/day03/da_data/aapl.csv', delimiter=',', usecols=(1,3,4,5,6),unpack=True, dtype='M8[D],f8,f8,f8,f8',converters={1:dmy2ymd})# 繪制收盤價折線圖 mp.figure('AAPL', facecolor='lightgray') mp.title('AAPL', fontsize=18) mp.xlabel('Date', fontsize=14) mp.ylabel('Price', fontsize=14) mp.grid(linestyle=':') # 設置刻度定位器 import matplotlib.dates as md ax = mp.gca() ax.xaxis.set_major_locator( # 每周一為主刻度md.WeekdayLocator(byweekday=md.MO)) # 每天一個次刻度 ax.xaxis.set_minor_locator(md.DayLocator()) # 設置主刻度文本格式 ax.xaxis.set_major_formatter(md.DateFormatter('%Y/%m/%d')) dates = dates.astype(md.datetime.datetime) mp.plot(dates, closing_prices, color='dodgerblue',label='Closing Price', linewidth=2,linestyle='--')# 線性預測 # 通過前6天的股票價格,整理A與B,得到x,預測第7天收盤價 N = 3 pred_prices = np.zeros(closing_prices.size - N*2) for i in range(pred_prices.size):A = np.zeros((N, N))for j in range(N):A[j,:] = closing_prices[j+i:i+j+N]B = closing_prices[N+i:N*2+i]x = np.linalg.lstsq(A, B)[0]# dot點積:B[0]*x[0] + B[1]*x[1] + B[2]*x[2]pred = B.dot(x)pred_prices[i] = predmp.plot(dates[N*2:], pred_prices, 'o-', color='orangered', label='Prediction Price')mp.legend() mp.gcf().autofmt_xdate() mp.show()線性擬合
線性擬合可以尋求與一組散點走向趨勢規律相適應的線型表達式方程。
有一組散點描述時間序列下的股價:
[x1, y1] [x2, y2] [x3, y3] ... [xn, yn]根據線型 y=kx + b 方程可得:
kx1 + b = y1 kx2 + b = y2 kx3 + b = y3 ... kxn + b = yn [ x 1 1 x 2 1 x 3 1 x n 1 ] × [ k b ] = [ y 1 y 2 y 3 y n ] \left[ \begin{array}{ccc} x{_1} & 1\\ x{_2} & 1\\ x{_3} & 1 \\ x{_n} & 1 \\ \end{array} \right ] \times \left[ \begin{array}{ccc} k\\ b\\ \end{array} \right ]= \left[ \begin{array}{ccc} y{_1}\\ y{_2}\\ y{_3}\\ y{_n}\\ \end{array} \right ] ?????x1?x2?x3?xn??1111??????×[kb?]=?????y1?y2?y3?yn???????
樣本過多,每兩組方程即可求得一組k與b的值。
np.linalg.lstsq(a, b) 可以通過最小二乘法求出所有結果中擬合誤差最小的k與b的值。
案例:利用線型擬合畫出股價的趨勢線
繪制趨勢線(趨勢可以表示為最高價、最低價、收盤價的均值):
協方差
通過兩組統計數據計算而得的協方差可以評估這兩組統計數據的相似程度。
樣本:
A = [a1, a2, ..., an] B = [b1, b2, ..., bn]平均值:
ave_a = (a1 + a2 +...+ an)/n ave_b = (b1 + b2 +...+ bn)/n離差(用樣本中的每一個元素減去平均數,求得數據的誤差程度):
dev_a = [a1, a2, ..., an] - ave_a dev_b = [b1, b2, ..., bn] - ave_b協方差
協方差可以簡單反映兩組統計樣本的相關性
cov_ab = ave(dev_a x dev_b) cov_ba = ave(dev_b x dev_a)案例:計算兩組數據的協方差,并繪圖觀察。
import numpy as np import matplotlib.pyplot as mpa = np.random.randint(1, 30, 10) b = np.random.randint(1, 30, 10) #平均值 ave_a = np.mean(a) ave_b = np.mean(b) #離差 dev_a = a - ave_a dev_b = b - ave_b #協方差 cov_ab = np.mean(dev_a * dev_b) cov_ba = np.mean(dev_b * dev_a) print('a與b數組:', a, b) # a與b數組: [ 4 28 22 28 14 12 19 2 26 5] [14 8 29 5 11 12 27 21 9 18] print('a與b樣本方差:', np.sum(dev_a**2)/(len(dev_a)-1), np.sum(dev_b**2)/(len(dev_b)-1)) # a與b樣本方差: 101.55555555555556 66.04444444444445 print('a與b協方差:',cov_ab, cov_ba) # a與b協方差: -22.9 -22.9 #繪圖,查看兩條圖線的相關性 mp.figure('COV LINES', facecolor='lightgray') mp.title('COV LINES', fontsize=16) mp.xlabel('x', fontsize=14) mp.ylabel('y', fontsize=14) x = np.arange(0, 10) #a,b兩條線 mp.plot(x, a, color='dodgerblue', label='Line1') mp.plot(x, b, color='limegreen', label='Line2') #a,b兩條線的平均線 mp.plot([0, 9], [ave_a, ave_a], color='dodgerblue', linestyle='--', alpha=0.7, linewidth=3) mp.plot([0, 9], [ave_b, ave_b], color='limegreen', linestyle='--', alpha=0.7, linewidth=3)mp.grid(linestyle='--', alpha=0.5) mp.legend() mp.tight_layout() mp.show()相關系數
協方差除去兩組統計樣本標準差的乘積是一個[-1, 1]之間的數。該結果稱為統計樣本的相關系數。
# a組樣本 與 b組樣本做對照后的相關系數 cov_ab / (std_a * std_b) # b組樣本 與 a組樣本做對照后的相關系數 cov_ba / (std_b * std_a) # a樣本與a樣本作對照 b樣本與b樣本做對照 二者必然相等 cov_ab / (std_a * std_b)=cov_ba/(std_b * std_a)通過相關系數可以分析兩組數據的相關性:
若相關系數越接近于0,越表示兩組樣本越不相關。 若相關系數越接近于1,越表示兩組樣本正相關。 若相關系數越接近于-1,越表示兩組樣本負相關。案例:輸出案例中兩組數據的相關系數。
print('相關系數:', cov_ab / (np.std(a) * np.std(b)), cov_ba / (np.std(a) * np.std(b))) 相關系數: 0.2208660975292323 0.2208660975292323相關矩陣
[ v a r _ a s t d _ a × s t d _ a c o v _ a b s t d _ a × s t d _ b c o v _ b a s t d _ b × s t d _ a v a r _ b s t d _ b × s t d _ b ] \left[ \begin{array}{c} \frac{var\_a}{std\_a \times std\_a} & \frac{cov\_ab}{std\_a \times std\_b} \\ \frac{cov\_ba}{std\_b \times std\_a} & \frac{var\_b}{std\_b \times std\_b}\\ \end{array} \right ] [std_a×std_avar_a?std_b×std_acov_ba??std_a×std_bcov_ab?std_b×std_bvar_b??]
矩陣正對角線上的值都為1。(同組樣本自己相比絕對正相關)
[ 1 c o v _ a b s t d _ a × s t d _ b c o v _ b a s t d _ b × s t d _ a 1 ] \left[ \begin{array}{ccc} 1 & \frac{cov\_ab}{std\_a \times std\_b} \\ \frac{cov\_ba}{std\_b \times std\_a} & 1\\ \end{array} \right ] [1std_b×std_acov_ba??std_a×std_bcov_ab?1?]
numpy提供了求得相關矩陣的API:
# 相關矩陣 numpy.corrcoef(a, b)# 相關矩陣的分子矩陣 即協方差矩陣 # [[a方差,ab協方差], [ba協方差, b方差]] numpy.cov(a, b) # 這個函數求的協方差用的是樣本方差(分母是n- 1)綜合兩支股票收盤價的漲跌情況求出協方差,相關系數,相關矩陣:
import numpy as np import matplotlib.pyplot as mp import datetime as dtdef dmy2ymd(dmy):dmy = str(dmy, encoding='utf-8')time = dt.datetime.strptime(dmy, '%d-%m-%Y').date()t = time.strftime('%Y-%m-%d')return tdates, vale_closing_prices = \np.loadtxt('C:/Users/ADMIN/Desktop/DATASCIENCE/vale.csv', delimiter=',', usecols=(1, 6),unpack=True, dtype='M8[D], f8',converters={1:dmy2ymd})bhp_closing_prices = np.loadtxt('C:/Users/ADMIN/Desktop/DATASCIENCE/bhp.csv', delimiter=',',usecols=(6,))# 計算協方差 vale_mean = np.mean(vale_closing_prices) bhp_mean = np.mean(bhp_closing_prices) vale_dev = vale_closing_prices - vale_mean bhp_dev = bhp_closing_prices - bhp_mean cov = np.mean(vale_dev * bhp_dev) print(cov) # 3.135577333333333# 相關系數 coef = cov / (bhp_closing_prices.std() * vale_closing_prices.std()) print(coef) # 0.8664988296368299# 相關矩陣 m = np.corrcoef(bhp_closing_prices, vale_closing_prices,) print(m, m[0,1]) # [[1. 0.86649883] # [0.86649883 1. ]] 0.86649882963683v = np.cov(bhp_closing_prices, vale_closing_prices) # 這個函數得到的 協方差矩陣里的元素 都是樣本方差(所以偏大),而上面我們算的是總體方差 print(v) # [[8.53844379 3.24370069] # [3.24370069 1.64122023]]多項式擬合
多項式的一般形式:
y = p 0 x n + p 1 x n ? 1 + p 2 x n ? 2 + p 3 x n ? 3 + . . . + p n y=p_{0}x^n + p_{1}x^{n-1} + p_{2}x^{n-2} + p_{3}x^{n-3} +...+p_{n} y=p0?xn+p1?xn?1+p2?xn?2+p3?xn?3+...+pn?
多項式擬合的目的是為了找到一組 p 0 , p 1 , . . . , p n p_0, p_1, ..., p_n p0?,p1?,...,pn?,使得擬合方程盡可能的與實際樣本數據相符合。
假設擬合得到的多項式如下:
f ( x ) = p 0 x n + p 1 x n ? 1 + p 2 x n ? 2 + p 3 x n ? 3 + . . . + p n f(x)=p_{0}x^n + p_{1}x^{n-1} + p_{2}x^{n-2} + p_{3}x^{n-3} +...+p_{n} f(x)=p0?xn+p1?xn?1+p2?xn?2+p3?xn?3+...+pn?
則擬合函數與真實結果的差方如下
l o s s = ( y 1 ? f ( x 1 ) ) 2 + ( y 2 ? f ( x 2 ) ) 2 + . . . + ( y n ? f ( x n ) ) 2 loss = (y_1-f(x_1))^2 + (y_2-f(x_2))^2 + ... + (y_n-f(x_n))^2 loss=(y1??f(x1?))2+(y2??f(x2?))2+...+(yn??f(xn?))2
那么多項式擬合的過程即為求取一組 p 0 , p 1 , . . . , p n p_0, p_1, ..., p_n p0?,p1?,...,pn?, 使得loss的值最小。
多項式擬合相關API:
根據一組樣本,并給出最高次冪,求出擬合系數 np.polyfit(X, Y, 最高次冪) -> P多項式運算相關API:
根據擬合系數與自變量求出擬合值, 由此可得擬合曲線坐標樣本數據 [X, Y'] np.polyval(P, X) -> Y'多項式函數求導,根據擬合系數求出多項式函數導函數的系數 np.polyder(P) -> Q 已知多項式系數Q 求多項式函數的根(與x軸交點的橫坐標) xs = np.roots(Q)兩個多項式函數的差函數的系數(可以通過差函數的根求取兩個曲線的交點) Q = np.polysub(P1, P2)案例:求多項式 y = 4x3 + 3x2 - 1000x + 1曲線駐點的坐標。
''' 1. 求出多項式的導函數 2. 求出導函數的根,若導函數的根為實數,則該點則為曲線駐點。 ''' import numpy as np import matplotlib.pyplot as mpP = [4, 3, -1000, 1]# 畫出函數圖像 x = np.linspace(-20, 20, 1000) y = np.polyval(P, x) mp.grid(linestyle=':') mp.plot(x, y)# 畫出駐點 Q = np.polyder(P) xs = np.roots(Q) print(xs) ys = np.polyval(P, xs) mp.scatter(xs, ys, s=100, marker='*',color='red', zorder=3) mp.show()
使用多項式函數擬合兩只股票bhp、vale的差價函數:
數據平滑
數據的平滑處理通常包含有降噪、擬合等操作。降噪的功能意在去除額外的影響因素,擬合的目的意在數學模型化,可以通過更多的數學方法識別曲線特征。
案例:繪制兩只股票收益率曲線。收益率 =(后一天收盤價-前一天收盤價) / 前一天收盤價
說明:
1、顏色最淺的兩條折線是收益線
2、顏色較淺的兩條折線是卷積降噪線
3、顏色最深的兩條折線是針對卷積結果,作出的多項式擬合曲線
符號數組
sign函數可以把樣本數組的變成對應的符號數組,正數變為1,負數變為-1,0則變為0。
ary = np.sign(源數組)凈額成交量(OBV)
成交量可以反映市場對某支股票的人氣,而成交量是一只股票上漲的能量。一支股票的上漲往往需要較大的成交量。而下跌時則不然。
若相比上一天的收盤價上漲,則為正成交量;若相比上一天的收盤價下跌,則為負成交量。
繪制OBV柱狀圖
dates, closing_prices, volumes = np.loadtxt('C:/Users/ADMIN/Desktop/DATASCIENCE/bhp.csv', delimiter=',',usecols=(1, 6, 7), unpack=True,dtype='M8[D], f8, f8', converters={1: dmy2ymd}) diff_closing_prices = np.diff(closing_prices) sign_closing_prices = np.sign(diff_closing_prices) # [ 1. -1. -1. 1. -1. -1. 1. -1. 1. 1. -1. 1. 1. -1. -1. -1. -1. -1. # 1. -1. -1. -1. 1. 1. 1. -1. 1. 1. -1.] obvs = volumes[1:] * sign_closing_prices mp.figure('On-Balance Volume', facecolor='lightgray') mp.title('On-Balance Volume', fontsize=20) mp.xlabel('Date', fontsize=14) mp.ylabel('OBV', fontsize=14) ax = mp.gca() ax.xaxis.set_major_locator(md.WeekdayLocator(byweekday=md.MO)) ax.xaxis.set_minor_locator(md.DayLocator()) ax.xaxis.set_major_formatter(md.DateFormatter('%d %b %Y')) mp.tick_params(labelsize=10) mp.grid(axis='y', linestyle=':') dates = dates[1:].astype(md.datetime.datetime) mp.bar(dates, obvs, 1.0, color='dodgerblue',edgecolor='white', label='OBV') mp.legend() mp.gcf().autofmt_xdate() mp.show()數組處理函數
ary = np.piecewise(源數組, 條件序列, 取值序列)針對源數組中的每一個元素,檢測其是否符合條件序列中的每一個條件,符合哪個條件就用取值系列中與之對應的值,表示該元素,放到目標 數組中返回。
條件序列: [a < 0, a == 0, a > 0]
取值序列: [-1, 0, 1]
a = np.array([70, 80, 60, 30, 40]) d = np.piecewise(a, [a < 60, a == 60, a > 60],[-1, 0, 1]) # d = [ 1 1 0 -1 -1]矢量化
矢量化指的是用數組代替標量來操作數組里的每個元素。
numpy提供了vectorize函數,可以把處理標量的函數矢量化,返回的函數可以直接處理ndarray數組。
``
vectorized_foo = np.vectorize(foo)
vectorized_foo(X, Y)
兩行代碼可以寫成:
np.vectorize(foo)(X, Y)
numpy還提供了frompyfunc函數,也可以完成與vectorize相同的功能:
# 把foo轉換成矢量函數,該矢量函數接收2個參數,返回一個結果 fun = np.frompyfunc(foo, 2, 1) fun(X, Y)案例:定義一種買進賣出策略,通過歷史數據判斷這種策略是否值得實施。
import numpy as np import matplotlib.pyplot as mp import datetime as dt import matplotlib.dates as mddef dmy2ymd(dmy):dmy = str(dmy, encoding='utf-8')time = dt.datetime.strptime(dmy, '%d-%m-%Y').date()t = time.strftime('%Y-%m-%d')return t dates, opening_prices, highest_prices, \lowest_prices, closing_prices = np.loadtxt('C:/Users/ADMIN/Desktop/DATASCIENCE/bhp.csv', delimiter=',',usecols=(1, 3, 4, 5, 6), unpack=True,dtype='M8[D], f8, f8, f8, f8',converters={1: dmy2ymd})# 定義一種投資策略 def profit(opening_price, highest_price,lowest_price, closing_price):buying_price = opening_price * 0.99if lowest_price <= buying_price <= highest_price:return (closing_price - buying_price) * \100 / buying_pricereturn np.nan # 無效值# 矢量化投資函數 profits = np.vectorize(profit)(opening_prices, highest_prices, lowest_prices, closing_prices) # 判斷無效值 nan = np.isnan(profits) dates, profits = dates[~nan], profits[~nan] gain_dates, gain_profits = dates[profits > 0], profits[profits > 0] loss_dates, loss_profits = dates[profits < 0], profits[profits < 0] # 繪制收盤價折線圖 mp.figure('Trading Simulation', facecolor='lightgray') mp.title('Trading Simulation', fontsize=20) mp.xlabel('Date', fontsize=14) mp.ylabel('Profit', fontsize=14) # 設置刻度定位器 ax = mp.gca() ax.xaxis.set_major_locator(md.WeekdayLocator(byweekday=md.MO)) # 每周一為主刻度 ax.xaxis.set_minor_locator(md.DayLocator()) # 每天一個次刻度 ax.xaxis.set_major_formatter(md.DateFormatter('%d %b %Y')) # 設置主刻度文本格式 mp.tick_params(labelsize=10) mp.grid(linestyle=':')# 繪制收益率折線 if dates.size > 0:dates = dates.astype(md.datetime.datetime)mp.plot(dates, profits, c='gray',label='Profit')mp.axhline(y=profits.mean(), linestyle='--',color='gray')# 繪制收益率為正的點和平均線 if gain_dates.size > 0:gain_dates = gain_dates.astype(md.datetime.datetime)mp.plot(gain_dates, gain_profits, 'o',c='orangered', label='Gain Profit')mp.axhline(y=gain_profits.mean(), linestyle='--',color='orangered')# 繪制收益率為負的點和平均線 if loss_dates.size > 0:loss_dates = loss_dates.astype(md.datetime.datetime)mp.plot(loss_dates, loss_profits, 'o',c='limegreen', label='Loss Profit')mp.axhline(y=loss_profits.mean(), linestyle='--',color='limegreen') mp.legend() mp.gcf().autofmt_xdate() mp.show()總結
以上是生活随笔為你收集整理的针对股票涨跌信息的一系列处理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Plan for the day
- 下一篇: P5737 【深基7.例3】闰年展示