Baru-baru ini, saya melihat buku harian kuantitatif BuOu
Perdagangan pasangan mata uang digital adalah strategi perdagangan berdasarkan arbitrase statistik, yang secara bersamaan membeli dan menjual dua cryptocurrency yang sangat berkorelasi untuk mendapatkan keuntungan dari penyimpangan harga.
Strategi perdagangan pasangan bergantung pada korelasi historis antara harga dua mata uang digital. Ketika harga dua mata uang menunjukkan korelasi yang kuat, tren harga mereka umumnya sinkronisasi. Jika rasio harga antara keduanya menyimpang secara signifikan pada saat tertentu, itu dapat dianggap sebagai kelainan sementara dan harga akan cenderung kembali ke level normal. Pasar mata uang digital sangat saling terkait. Ketika mata uang digital utama (seperti Bitcoin) berfluktuasi secara signifikan, itu biasanya akan memicu reaksi terkoordinasi di mata uang digital lainnya. Beberapa mata uang mungkin memiliki korelasi positif yang sangat jelas yang dapat berlangsung karena institusi investasi yang sama, pembuat pasar yang sama, dan jalur yang sama. Beberapa mata uang berkorelasi negatif, tetapi ada lebih sedikit mata uang yang berkorelasi negatif, dan karena mereka semua dipengaruhi oleh tren pasar, mereka sering akan memiliki tren pasar yang konsisten.
Misalkan mata uang A dan mata uang B memiliki korelasi harga yang tinggi. Pada saat tertentu, nilai rata-rata rasio harga A/B adalah 1. Jika pada saat tertentu, rasio harga A/B menyimpang lebih dari 0,001, yaitu lebih dari 1,001, maka Anda dapat berdagang dengan cara berikut: Buka posisi panjang pada B dan buka posisi pendek pada A. Sebaliknya, ketika rasio harga A/B lebih rendah dari 0,999: Buka posisi panjang pada A dan buka posisi pendek pada B.
Kunci untuk profitabilitas terletak pada keuntungan spread ketika harga menyimpang dari rata-rata dan kembali normal.
Kode-kode ini dapat digunakan secara langsung. Yang terbaik adalah mengunduh Anancoda dan debugnya di notebook Jupyer. Ini termasuk paket untuk analisis data yang umum digunakan secara langsung.
import requests
from datetime import date,datetime
import time
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import requests, zipfile, io
%matplotlib inline
Info = requests.get('https://fapi.binance.com/fapi/v1/exchangeInfo')
b_symbols = [s['symbol'] for s in Info.json()['symbols'] if s['contractType'] == 'PERPETUAL' and s['status'] == 'TRADING' and s['quoteAsset'] == 'USDT']
b_symbols = list(filter(lambda x: x[-4:] == 'USDT', [s.split('_')[0] for s in b_symbols]))
b_symbols = [x[:-4] for x in b_symbols]
print(b_symbols) # Get all trading pairs being traded
Fungsi utama fungsi GetKlines adalah untuk mendapatkan data K-line historis dari kontrak abadi pasangan perdagangan yang ditentukan dari bursa Binance dan menyimpan data dalam Pandas DataFrame. Data K-line mencakup informasi seperti harga pembukaan, harga tertinggi, harga terendah, harga penutupan, dan volume perdagangan. Kali ini kami terutama menggunakan data harga penutupan.
def GetKlines(symbol='BTCUSDT',start='2020-8-10',end='2024-7-01',period='1h',base='fapi',v = 'v1'):
Klines = []
start_time = int(time.mktime(datetime.strptime(start, "%Y-%m-%d").timetuple()))*1000 + 8*60*60*1000
end_time = min(int(time.mktime(datetime.strptime(end, "%Y-%m-%d").timetuple()))*1000 + 8*60*60*1000,time.time()*1000)
intervel_map = {'m':60*1000,'h':60*60*1000,'d':24*60*60*1000}
while start_time < end_time:
time.sleep(0.3)
mid_time = start_time+1000*int(period[:-1])*intervel_map[period[-1]]
url = 'https://'+base+'.binance.com/'+base+'/'+v+'/klines?symbol=%s&interval=%s&startTime=%s&endTime=%s&limit=1000'%(symbol,period,start_time,mid_time)
res = requests.get(url)
res_list = res.json()
if type(res_list) == list and len(res_list) > 0:
start_time = res_list[-1][0]+int(period[:-1])*intervel_map[period[-1]]
Klines += res_list
if type(res_list) == list and len(res_list) == 0:
start_time = start_time+1000*int(period[:-1])*intervel_map[period[-1]]
if mid_time >= end_time:
break
df = pd.DataFrame(Klines,columns=['time','open','high','low','close','amount','end_time','volume','count','buy_amount','buy_volume','null']).astype('float')
df.index = pd.to_datetime(df.time,unit='ms')
return df
Volume data relatif besar. Untuk mengunduh lebih cepat, hanya data K-line per jam tiga bulan terakhir yang diperoleh. df_close berisi data harga penutupan semua mata uang.
start_date = '2024-04-01'
end_date = '2024-07-05'
period = '1h'
df_dict = {}
for symbol in b_symbols:
print(symbol)
if symbol in df_dict.keys():
continue
df_s = GetKlines(symbol=symbol+'USDT',start=start_date,end=end_date,period=period)
if not df_s.empty:
df_dict[symbol] = df_s
df_close = pd.DataFrame(index=pd.date_range(start=start_date, end=end_date, freq=period),columns=df_dict.keys())
for symbol in symbols:
df_close[symbol] = df_dict[symbol].close
df_close = df_close.dropna(how='all')
Kami mendefinisikan objek pertukaran untuk backtest berikut.
class Exchange:
def __init__(self, trade_symbols, fee=0.0002, initial_balance=10000):
self.initial_balance = initial_balance #Initial assets
self.fee = fee
self.trade_symbols = trade_symbols
self.account = {'USDT':{'realised_profit':0, 'unrealised_profit':0, 'total':initial_balance,
'fee':0, 'leverage':0, 'hold':0, 'long':0, 'short':0}}
for symbol in trade_symbols:
self.account[symbol] = {'amount':0, 'hold_price':0, 'value':0, 'price':0, 'realised_profit':0,'unrealised_profit':0,'fee':0}
def Trade(self, symbol, direction, price, amount):
cover_amount = 0 if direction*self.account[symbol]['amount'] >=0 else min(abs(self.account[symbol]['amount']), amount)
open_amount = amount - cover_amount
self.account['USDT']['realised_profit'] -= price*amount*self.fee #Deduction fee
self.account['USDT']['fee'] += price*amount*self.fee
self.account[symbol]['fee'] += price*amount*self.fee
if cover_amount > 0: #Close the position first
self.account['USDT']['realised_profit'] += -direction*(price - self.account[symbol]['hold_price'])*cover_amount #profit
self.account[symbol]['realised_profit'] += -direction*(price - self.account[symbol]['hold_price'])*cover_amount
self.account[symbol]['amount'] -= -direction*cover_amount
self.account[symbol]['hold_price'] = 0 if self.account[symbol]['amount'] == 0 else self.account[symbol]['hold_price']
if open_amount > 0:
total_cost = self.account[symbol]['hold_price']*direction*self.account[symbol]['amount'] + price*open_amount
total_amount = direction*self.account[symbol]['amount']+open_amount
self.account[symbol]['hold_price'] = total_cost/total_amount
self.account[symbol]['amount'] += direction*open_amount
def Buy(self, symbol, price, amount):
self.Trade(symbol, 1, price, amount)
def Sell(self, symbol, price, amount):
self.Trade(symbol, -1, price, amount)
def Update(self, close_price): #Update the assets
self.account['USDT']['unrealised_profit'] = 0
self.account['USDT']['hold'] = 0
self.account['USDT']['long'] = 0
self.account['USDT']['short'] = 0
for symbol in self.trade_symbols:
if not np.isnan(close_price[symbol]):
self.account[symbol]['unrealised_profit'] = (close_price[symbol] - self.account[symbol]['hold_price'])*self.account[symbol]['amount']
self.account[symbol]['price'] = close_price[symbol]
self.account[symbol]['value'] = self.account[symbol]['amount']*close_price[symbol]
if self.account[symbol]['amount'] > 0:
self.account['USDT']['long'] += self.account[symbol]['value']
if self.account[symbol]['amount'] < 0:
self.account['USDT']['short'] += self.account[symbol]['value']
self.account['USDT']['hold'] += abs(self.account[symbol]['value'])
self.account['USDT']['unrealised_profit'] += self.account[symbol]['unrealised_profit']
self.account['USDT']['total'] = round(self.account['USDT']['realised_profit'] + self.initial_balance + self.account['USDT']['unrealised_profit'],6)
self.account['USDT']['leverage'] = round(self.account['USDT']['hold']/self.account['USDT']['total'],3)
Perhitungan korelasi adalah metode dalam statistik yang digunakan untuk mengukur hubungan linier antara dua variabel. Metode perhitungan korelasi yang paling umum digunakan adalah koefisien korelasi Pearson. Berikut adalah prinsip, rumus dan metode implementasi perhitungan korelasi. Koefisien korelasi Pearson digunakan untuk mengukur hubungan linier antara dua variabel, dan kisaran nilainya antara -1 dan 1:
Koefisien korelasi Pearson menentukan korelasi antara dua variabel dengan menghitung kovarian dan standar deviasi mereka.
di mana:
Tentu saja, Anda tidak perlu terlalu khawatir tentang bagaimana hal itu dihitung. Anda dapat menggunakan 1 baris kode di Python untuk menghitung korelasi semua mata uang. Gambar menunjukkan peta panas korelasi. Merah mewakili korelasi positif, biru mewakili korelasi negatif, dan semakin gelap warnanya, semakin kuat korelasi. Anda dapat melihat bahwa sebagian besar area merah gelap, sehingga korelasi positif mata uang digital sangat kuat.
import seaborn as sns
corr = df_close.corr()
plt.figure(figsize=(20, 20))
sns.heatmap(corr, annot=False, cmap='coolwarm', vmin=-1, vmax=1)
plt.title('Correlation Heatmap of Cryptocurrency Closing Prices', fontsize=20);
Berdasarkan korelasi, 20 pasangan mata uang teratas yang paling berkorelasi dipilih. Hasilnya adalah sebagai berikut.
MANA SAND 0.996562
ICX ZIL 0.996000
STORJ FLOW 0.994193
FLOW SXP 0.993861
STORJ SXP 0.993822
IOTA ZIL 0.993204
SAND 0.993095
KAVA SAND 0.992303
ZIL SXP 0.992285
SAND 0.992103
DYDX ZIL 0.992053
DENT REEF 0.991789
RDNT MANTA 0.991690
STMX STORJ 0.991222
BIGTIME ACE 0.990987
RDNT HOOK 0.990718
IOST GAS 0.990643
ZIL HOOK 0.990576
MATIC FLOW 0.990564
MANTA HOOK 0.990563
Kode yang sesuai adalah sebagai berikut:
corr_pairs = corr.unstack()
# Remove self-correlation (i.e. values on the diagonal)
corr_pairs = corr_pairs[corr_pairs != 1]
sorted_corr_pairs = corr_pairs.sort_values(kind="quicksort")
# Extract the top 20 most and least correlated currency pairs
most_correlated = sorted_corr_pairs.tail(40)[::-2]
print("The top 20 most correlated currency pairs are:")
print(most_correlated)
Kode backtest spesifik adalah sebagai berikut. Strategi demonstrasi terutama mengamati rasio harga dua cryptocurrency (IOTA dan ZIL) dan perdagangan sesuai dengan perubahan rasio ini. Langkah-langkah spesifik adalah sebagai berikut:
e
dengan saldo awal $ 10.000 dan biaya transaksi 0,02%.avg
.value = 1000
.df_close
.diff
.aim_value
, dan satu nilai diperdagangkan untuk setiap 0.01 penyimpangan.pair_a
dan belipair_b
operations.pair_a
dan menjualpair_b
operasi dilakukan.avg
untuk mencerminkan rasio harga terbaru.res_list
.res_list
ke dataframeres
untuk analisis dan presentasi lebih lanjut.pair_a = 'IOTA'
pair_b = "ZIL"
e = Exchange([pair_a,pair_b], fee=0.0002, initial_balance=10000) #Exchange definition is placed in the comments section
res_list = []
index_list = []
avg = df_close[pair_a][0] / df_close[pair_b][0]
value = 1000
for idx, row in df_close.iterrows():
diff = (row[pair_a] / row[pair_b] - avg)/avg
aim_value = -value * diff / 0.01
if -aim_value + e.account[pair_a]['amount']*row[pair_a] > 0.5*value:
e.Sell(pair_a,row[pair_a],(-aim_value + e.account[pair_a]['amount']*row[pair_a])/row[pair_a])
e.Buy(pair_b,row[pair_b],(-aim_value - e.account[pair_b]['amount']*row[pair_b])/row[pair_b])
if -aim_value + e.account[pair_a]['amount']*row[pair_a] < -0.5*value:
e.Buy(pair_a, row[pair_a],(aim_value - e.account[pair_a]['amount']*row[pair_a])/row[pair_a])
e.Sell(pair_b, row[pair_b],(aim_value + e.account[pair_b]['amount']*row[pair_b])/row[pair_b])
avg = 0.99*avg + 0.01*row[pair_a] / row[pair_b]
index_list.append(idx)
e.Update(row)
res_list.append([e.account['USDT']['total'],e.account['USDT']['hold'],
e.account['USDT']['fee'],e.account['USDT']['long'],e.account['USDT']['short']])
res = pd.DataFrame(data=res_list, columns=['total','hold', 'fee', 'long', 'short'],index = index_list)
res['total'].plot(grid=True);
Total 4 kelompok mata uang diuji kembali, dan hasilnya ideal. Perhitungan korelasi saat ini menggunakan data masa depan, sehingga tidak terlalu akurat. Artikel ini juga membagi data menjadi dua bagian, berdasarkan perhitungan korélasi sebelumnya dan perdagangan backtest berikutnya. Hasilnya sedikit berbeda tetapi tidak buruk. Kami biarkan pengguna untuk berlatih dan memverifikasi.
Meskipun strategi perdagangan pasangan dapat menguntungkan dalam teori, masih ada beberapa risiko dalam operasi yang sebenarnya: korelasi antara mata uang dapat berubah dari waktu ke waktu, menyebabkan strategi gagal; di bawah kondisi pasar yang ekstrim, penyimpangan harga dapat meningkat, menghasilkan kerugian yang lebih besar; likuiditas rendah mata uang tertentu dapat membuat transaksi sulit untuk dilaksanakan atau meningkatkan biaya; dan biaya yang dihasilkan oleh transaksi yang sering dapat mengikis keuntungan.
Untuk mengurangi risiko dan meningkatkan stabilitas strategi, langkah-langkah perbaikan berikut dapat dipertimbangkan: secara teratur menghitung kembali korelasi antara mata uang dan menyesuaikan pasangan perdagangan secara tepat waktu; menetapkan stop loss dan mengambil titik keuntungan untuk mengendalikan kerugian maksimum dari satu transaksi; perdagangan beberapa pasangan mata uang pada saat yang sama untuk mendiversifikasi risiko.
Strategi perdagangan pasangan mata uang digital mencapai keuntungan dengan memanfaatkan korelasi harga mata uang dan melakukan operasi arbitrase ketika harga menyimpang. Strategi ini memiliki kelayakan teoritis yang tinggi.