關(guān)鍵詞
Pandas Sqlite3
GitHub
思路
當(dāng)前只計(jì)算某只股票最多一年的指標(biāo)啦桌,常見的5天伪冰,10天掀鹅,20天和一年的指標(biāo)任岸。
從數(shù)據(jù)庫中拿到某只股票一年的K線數(shù)據(jù),振幅指標(biāo)只需要自己的數(shù)據(jù)疚顷,貝塔系數(shù)需要對比大盤的數(shù)據(jù)跋核,上海交易所的股票就用上證指數(shù)計(jì)算除抛,深圳交易所的股票就用深成指來計(jì)算薯酝。
讀數(shù)據(jù)庫
從數(shù)據(jù)庫中讀取某只股票的K線數(shù)據(jù)半沽,上一篇有說到 pandas.to_sql() 方法存數(shù)據(jù)不太好用,但是pandas.read_sql()方法可以比較方便的讀取數(shù)據(jù)吴菠,而且返回?cái)?shù)據(jù)結(jié)構(gòu)就是DataFrame者填,便于我們計(jì)算。
- 讀取上證指數(shù)
from sqlalchemy import create_engine
import pandas as pd
import datetime
db = create_engine('sqlite:///mystock.db')
sql_cmd = "SELECT * FROM stock_day_k where code='sh.000001' order by date desc limit 0,251"
datash = pd.read_sql(sql=sql_cmd, con=db)
這里我們用251天的原因是一年的交易天數(shù)大概是251天做葵。用date倒序取251行就大概是一年的K線數(shù)據(jù)占哟。
- 讀取股票K線
讀取單只股票K線數(shù)據(jù)和讀取上證指數(shù)是一樣的,只是有些股票可能會存在停盤的情況酿矢,所以判斷如果十個(gè)交易日都是非交易狀態(tài)榨乎,這個(gè)股票就先不計(jì)算了。
想拿到交易狀態(tài)瘫筐,數(shù)據(jù)中有一列列名是 'tradestatus'蜜暑,用dataframe['columnname']就可以拿到一整列數(shù)據(jù)。
sql_cmd = "SELECT * FROM stock_day_k where code='" + ticker+"' order by date desc limit 0,251"
daily = pd.read_sql(sql=sql_cmd, con=db)
if tradestatus == 0:
count = 0
canSkip = False
for tradestatus2 in daily['tradestatus']:
if tradestatus2 == 1:
break
count += 1
if count ==10:
canSkip = True
break
if canSkip:
continue
- 數(shù)據(jù)處理
從數(shù)據(jù)庫中拿到的數(shù)據(jù)严肪,是根據(jù)日期倒序排列的史煎,這里需要升序排序,并把索引重置驳糯。
daily = daily.sort_values(by='date', ascending=True)
daily = daily.reset_index(drop = True)
給數(shù)據(jù)加一列篇梭,計(jì)算所有日期和第一天的相對價(jià)格,close就是某日的收盤價(jià)格酝枢。
daily['relaprice'] = daily['close']/daily['close'][0]
- 計(jì)算貝塔系數(shù)
找了一些計(jì)算貝塔系數(shù)的方法恬偷,Scipy里scipy.stats.linregress函數(shù)可以直接計(jì)算。 取一段時(shí)間內(nèi)大盤的相對數(shù)據(jù)和某只股票的相對數(shù)據(jù)來計(jì)算帘睦,考慮到有些股票可能沒有比較新袍患,時(shí)間不夠一年或者一個(gè)月,如果想計(jì)算的日期數(shù)比股票的數(shù)據(jù)還多的話竣付,最后取時(shí)間區(qū)間為股票的時(shí)間诡延。
用 array[-N:] 來獲取數(shù)組的最后N個(gè)數(shù)據(jù)。
#relaticker = daily['relaprice']
#relash = datash['relaprice']
from scipy import stats
def cal_alpha_beta(relash, relaticker, dayNumber=0):
if dayNumber > relaticker.shape[0]:
return np.nan,np.nan,np.nan
if dayNumber == 0:
dayNumber = relaticker.shape[0]
beta,alpha,r_value,p_value,std_err=stats.linregress(relash[-dayNumber:], relaticker[-dayNumber:])
return alpha,beta,r_value**2
- 計(jì)算相關(guān)系數(shù)
相關(guān)系數(shù)是另一個(gè)股票與大盤的對比指標(biāo)古胆。Pandas有提供現(xiàn)成的方法pandas.DataFrame.pct_change肆良,需要將股票數(shù)據(jù)和大盤數(shù)據(jù)組合在一起
# 用sh.000001和sh.000002為例,將第二個(gè)數(shù)據(jù)的close列連接到sh.000001數(shù)據(jù)
price = DataFrame({'date': datash['date'], 'sh.000001':datash['close']})
pp = DataFrame({'sh.000002':daily['close']})
#拼接
price2 = pd.concat([price, pp], axis=1)
#按照date升序排列
price2 = price2.sort_values(by='date', ascending=True)
#把date列去掉逸绎,因?yàn)橛?jì)算的時(shí)候不需要這一列了
price2 = price2.drop(['date'], axis=1)
#去除索引
price2 = price2.reset_index(drop = True)
corr, cov = cal_correlation(price2, pp.shape[0])
def cal_correlation(price, length, dayNumber=0):
if dayNumber >length:
return np.nan,np.nan
if dayNumber == 0:
dayNumber = length
#獲取后N個(gè)數(shù)據(jù)
pricelastN = price.tail(dayNumber)
returns = pricelastN.pct_change()
corr=returns.corr()
cov=returns.cov()
return corr.iloc[1][0],cov.iloc[1][0]
- 計(jì)算振幅
振幅這個(gè)比較簡單惹恃,計(jì)算起來也比較簡單
#dayK 就是股票的K線數(shù)據(jù)
def cal_amplitude(dayK,dayNumber=0):
if dayNumber > dayK.shape[0]:
return np.nan
if dayNumber == 0:
dayNumber = dayK.shape[0]
dailylastN = dayK.tail(dayNumber)
maxhigh = dailylastN['high'].max()
minlow = dailylastN['low'].min()
amplitude = (maxhigh - minlow)/dailylastN['preclose'].iloc[0]
return amplitude
- 其他指標(biāo)
后續(xù)再想想。棺牧。巫糙。