天天看點

Python數字貨币量化交易

在數字貨币量化領域的資料實在是太少了,我總結了一下我的經驗(以火币交易所為例)以供小白參考

第一步:申請api key和secret,

第二步:檢視交易所的api文檔(https://huobiapi.github.io/docs/spot/v1/cn/#185368440e)

第三步:這裡其實是困擾很多小白的一部,就是拿到了api不知道該怎麼用,首先火币提供了不同語言版本的sdk,可以利用這些sdk中提供的方法來查詢曆史k線,盤口情況,實時價格以及常用的各種資訊,當然也可以選擇一些封裝好的第三方庫比如ccxt,來實作上述資料的擷取。一般來說ccxt這種庫會對資料格式進行進一步處理,使用起來友善,而火币原生的sdk隻是提供方法,後面的資料處理得自己實作,就比如原生sdk擷取的曆史k線是按時間降序排序的,你計算ma的時候還要自己重新排序,但如果想要實作一個量化系統的話還是建議使用sdk好一點,自己寫輪子友善調用

第四步:就是把自己的交易邏輯用代碼實作,比如使用雙均線政策,

huobipro = ccxt.huobipro({
    'apiKey': '',
    'secret': '',
})      

先使用ccxt擷取交易所的執行個體,然後擷取曆史k線,得到的資料使用dataframe格式接受

huobipro.fetch_ohlcv(symbol=symbol, limit=limit_num, timeframe=timeframe)      

然後利用pandas提供的函數計算MA,

df['median_short'] = df['close'].rolling(n_short, min_periods=1).mean()      
df['median_long'] = df['close'].rolling(n_long, min_periods=1).mean()      

然後再找出買入賣出信号,

# 找出買入信号
condition1 = df['median_short'] > df['median_long']  # 短均線上穿長均線
condition2 = df['median_short'].shift(1) <= df['median_long'].shift(1)
df.loc[condition1 & condition2, 'signal'] = 1  # 産生買入信号的k線标記為1
# 找出賣出信号
condition1 = df['median_short'] < df['median_long']  # 短均線上穿長均線
condition2 = df['median_short'].shift(1) >= df['median_long'].shift(1)
df.loc[condition1 & condition2, 'signal'] = 0  # 産生賣出信号的k線标記為0      

有了交易信号,就可以擷取信号,再判斷進行下單(huobipro.create_limit_buy/sell_order()了)

第五步:其實第四步就可以交易了,第五步是回測,一般來說先回測再根據回測結果選用政策,最後才進行實盤

回測分析的相關有很多種,在這方面我也不是很懂,目前我還是習慣用累計利潤來進行分析,

# 由signal計算出實際的每天持倉
df['pos'] = df['signal'].shift()
df['pos'].fillna(method='ffill', inplace=True)
df['pos'].fillna(value=0, inplace=True)      

到這裡持倉信号就有了,就可以根據持倉和曆史k線的價格計算累計利潤了,

df['change'] = df['close'].pct_change(1)  # 根據收盤價計算漲跌幅
df['by_at_open_change'] = df['close'] / df['open'] - 1  # 開盤買入到收盤的漲跌幅
df['sell_next_open_change'] = df['open'].shift(-1) / df['close'] - 1  # 這根收盤到下根開盤的漲跌幅
df.at[len(df) - 1, 'sell_next_open_change'] = 0  # 補全空值 df.at[4, 'B']
# 選取開倉條件
condition1 = df['pos'] == 1
condition2 = df['pos'] != df['pos'].shift(1)
open_pos_condition = condition1 & condition2
# 選取平倉條件
condition1 = df['pos'] == 0
condition2 = df['pos'] != df['pos'].shift(1)
close_pos_condition = condition1 & condition2
# 對每次交易進行分組
df.loc[open_pos_condition, 'start_time'] = df['open_time']
df['start_time'].fillna(method='ffill', inplace=True)
df.loc[df['pos'] == 0, 'start_time'] = pd.NaT
init_cash = 1000  # 初始資金
# 計算倉位變動
# 開倉時倉位
df.loc[open_pos_condition, 'position'] = init_cash * (1 + df['by_at_open_change'])
group_num = len(df.groupby('start_time'))
if group_num > 1:
    temp = df.groupby('start_time').apply(lambda x: x['close'] / x.iloc[0]['close'] * x.iloc[0]['position'])
    temp = temp.reset_index(level=[0])
    df['position'] = temp['close']
df['position_max'] = df['position'] * df['high'] / df['close']
df['position_min'] = df['position'] * df['low'] / df['close']
# #平倉時的倉位
# df.loc[close_pos_condition,'position']*=(1+df.loc[close_pos_condition,'sell_next_open_change'])
# 計算持倉利潤
df['porfit'] = (df['position'] - init_cash) * df['pos']  # 持倉利潤或虧損
# df.loc[df['pos']==1,'porfit_min']=(df['position_min']-init_cash)*df['pos'] #最小持倉盈利或虧損
# df.loc[df['pos']==0,'porfit_max']=(df['position_max']-init_cash)*df['pos']
# 計算實際資金量
df['cash'] = init_cash + df['porfit']  # 實際資金
# 計算資金曲線
df['equity_change'] = df['cash'].pct_change()
# 開倉日收益率
df.loc[open_pos_condition, 'equity_change'] = df.loc[open_pos_condition, 'cash'] / init_cash - 1
df['equity_change'].fillna(value=0, inplace=True)
df['equity_curve'] = (1 + df['equity_change']).cumprod()
df['equity_curve'] = df['equity_curve'] * init_cash      

從回測結果來看,雙均線政策比較吃單邊行情,震蕩行情的話基本就是送手續費,而且比較适合大周期,日線級别啥的,不适合高頻交易,以bsv為例,bsv是回測結果比較好的

Python數字貨币量化交易
Python數字貨币量化交易

實際走勢:

Python數字貨币量化交易

以投入1000u為例,不考慮手續費的情況下,每天的資金情況如回測結果所示,最小640,最大10521,十倍,基本算是約等于bsv的最大漲幅,但還有很多小波段沒吃到,而且周期算是比較長的,btc回測也有3倍左右,最慘的是山寨,基本都是虧損

嗯,先寫這麼多,後面有想法了再更,可能是可視化回測方面的

可以看到其自上線最低價為49.17,最高價為455.55,最大漲幅為9.26倍.如果2018年12月6号91買入,現價192.5,持倉到現在利潤約為2.11倍,而該系統的收益為8.43倍.也就是說該系統的雙均線政策遠遠領先不操作的收益.但是也應該看到該币種最大漲幅為9.26倍,該政策尚未領先其最大漲幅,

可以看到其自上線最低價為49.17,最高價為455.55,最大漲幅為9.26倍.如果2018年12月6号91買入,現價192.5,持倉到現在利潤約為2.11倍,而該系統的收益為8.43倍.也就是說該系統的雙均線政策遠遠領先不操作的收益.但是也應該看到該币種最大漲幅為9.26倍,該政策尚未領先其最大漲幅,