Skip to main content

Conintegration method

Project description

This programme is used for statistical arbitrage with co integation method

Dependencies

  • python 3.5

  • pandas 0.22.0

  • spyder 3.2.8

  • joblib 0.12.3

  • RNWS 0.1.2

  • mini_exchange 0.0.7

Sample

Back Test

Calculate p_value of stationarity among all pairs along all history

import pandas as pd
from CointArbitrage.pairing_period import find_pair,filter_tickers

price=pd.read('price.csv') # index:yyyymmdd(int),columns:tickers,values:adjusted price

past_date=60 # use last 60 days to calculate p_value
P=[]
for i in range(past_date,price.shape[0]):
    # filter unavailable tickers, this step is optional
    df=filter_tickers(price.iloc[(i-past_date):i])
    # calculate p_value
    des=find_pair(df,mul=True,n_jobs=-1)
    dt=filter_tickers.index[i]
    P.append(pd.Series(des.p_value.values,index=des['ticker1'].str.cat(des['ticker2'],'|').values,name=dt))
pairs=pd.concat(P,axis=1).T

Make signal dataframe

from CointArbitrage.trading_period import zscore_log_w,zscore_w,sig,sig_cut_tail
window=20 # use 20 days to calculate zscore ( = normalize(stockPrice1/stockPrice2))
ratio,zs=zscore_w(price_df=price,pair_lst=pairs.columns,window=window)
# or use log zscore = normalize(log(stockPrice1/stockPrice2))
ratio,zs=zscore_log_w(price_df=price,pair_lst=pairs.columns,window=window)
# or use exponential moving to calculate zscore with function zscore_df and zscore_log_df

# generate signal
# k0: close position, int, float or pd.Series if need to specify different values for each pairs
# k1: open position
# k2: close out position
k0,k1,k2=1,2,4
sig_df=sig(zscore=zs,k0=k0,k1=k1,k2=k2)
# sig_df contains value Nan,-3,-2,-1,0,1,2,3
# 3(-3) means close position and open another position in different direction
# 2(-2) means close position
# 1(-1) means open position
# keep signal when stationary (i.e. p_val<0.1), others would be kept in Nan
# and add a new signal 4(-4), which means reaching the end of stationarity period
sig_result=sig_cut_tail(sig_df,pairs<0.1,n_jobs=-1,new_signal=4)

Simulate trade

from CointArbitrage.trading_period import Trade
start=20140101
end=20180101
TT=Trade(price,start=start,end=end)
user_name='user01'
TT.add_user(user_name,sig_result,start_amount=1000)
# add signal 4 as close signal
# and leave close status as -1 (default close status is 0)
# more reference can be found in mini_exchange package
TT.add_close_signal(4,close_status=-1)
TT.add_close_signal(-4,close_status=-1)
# trade 10 dollars when opening position each time
uad=pd.DataFrame({'user_name':[user_name],'amt_type':0,'value':10})
TT.trade(uad)
print(TT.summary())
# to analysis in detail, get the account info and position info of user01
account,position=TT.get_user(user_name)
# more details can be found in mini_exchange package
account.plot_history(by_pct=True)
account.annual_return()
account.draw_down()
account.romad()
position.win_rate(dual=True)
position.log
# plot one pair
pair='0001.HK|0002.HK'
TT.plot_trade_pair(user_name,pair,k0=k0,k1=k1,k2=k2,window=window)

Instant simulation in HK market with Wind Api

Find New Pair

# initialize
from CointArbitrage.instant_with_wind import init_log
init_log('log.csv')

# last t trading days
from WindPy import w
from CointArbitrage.instant_with_wind import trading_times
w.start()
times=trading_times(w,length=60,text="TradingCalendar=HKEX")

# download adjusted close price up to yesterday
# price is kept in file price_yyyymmdd.csv with eachline as 'tickers,values'
# more can be found in RNWS package
from CointArbitrage.instant_with_wind import download_hist_price
tickers=['0001.HK','0002.HK','0003.HK'...]
download_hist_price(tickers,times,'price_path',w)

# read in history price
from RNWS import read_df
hist_price=read_df('price_path',file_pattern='price',dt_range=times)

# filter stationary pairs
from CointArbitrage.pairing_period import filter_pval
import pandas as pd
pairs=['0001.HK|0002.HK','0001.HK|0003.HK',...]
new_pairs=filter_pval(hist_price,pairs,n_jobs=-1)
new_tickers=pd.Series(new_pairs).str.split('|',expand=True).unstack().unique().tolist()
new_hist=hist_price[new_tickers]

# lotsize and shortability
ls=pd.DataFrame({'shortable':[0,0,1,...],'lotsize':[500,1000,500,...]},index=['0001.HK','0002.HK','0003.HK'...])

# find new pairs
from CointArbitrage.instant_with_wind import find_new_hk
params={'log_path':'log.csv'
        ,'hist_price':hist_price
        ,'hist_log': pd.read_csv('history_log.csv') #from back test
        ,'pairs':new_pairs
        ,'tickers':new_tickers
        ,'zs_window':20
        ,'zs_log':False
        ,'w':w
        ,'ls':ls
        ,'potential_path':'potential_path.csv'
        ,'potential_k':1.8
        ,'k0':1
        ,'k1':2
        ,'k1':4
        ,'match_max':50000
        }

# update log.csv
sign=find_new_hk(**params)

update file every 1800s at trading hour and refresh evrey 900s at lunch break and before trading start

from CointArbitrage.instant_with_wind import time_sleep
time_sleep(sign={0:1800,1:900,2:'break',3:'break'})(find_new_hk)(**params)

Refresh log and check close status

params2={}
for key in ['log_path','hist_price','w','hist_log','k0','k2','plot_mark','potential_path','zs_log','zs_window']:
    params2.update(params[key])
refresh_hk(**params2)
# to continue refresh every 1800s
time_sleep(sign={0:1800,1:900,2:'break',3:'break'})(refresh_hk)(**params2)

Check stationarity by using the price at last 10min of all trading hours

param3={}
for key in ['log_path','hist_price','w','zs_window','zs_log','k0','k1']
    param3.update(key)
time_sleep(sign={0:10,1:9000,2:'break',3:'break'})(last_hk)(**param3)

Notice: After using time_sleep, sleep loops will start directly. Thus find_new, refresh and last should be running in 3 different consules.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

CointArbitrage-0.0.63-py3-none-any.whl (21.9 kB view details)

Uploaded Python 3

File details

Details for the file CointArbitrage-0.0.63-py3-none-any.whl.

File metadata

  • Download URL: CointArbitrage-0.0.63-py3-none-any.whl
  • Upload date:
  • Size: 21.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.11.0 pkginfo/1.4.2 requests/2.14.2 setuptools/40.2.0 requests-toolbelt/0.8.0 tqdm/4.23.4 CPython/3.5.5

File hashes

Hashes for CointArbitrage-0.0.63-py3-none-any.whl
Algorithm Hash digest
SHA256 0da457348a1e7343dd22f47873be49bc38ee25cb5dea347eb9e6b96771ca450a
MD5 b0930b7ae84b13cd62139791f1205a33
BLAKE2b-256 bd944b054b04371516186f38d7d6d74ccb262d8a7074fecc27fa8c340a4be9b6

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page