Baru-baru ini, saya melihat BuOu
Perdagangan pasangan mata wang digital adalah strategi perdagangan berdasarkan arbitraj statistik, yang pada masa yang sama membeli dan menjual dua mata wang kripto yang sangat berkaitan untuk memperoleh keuntungan dari penyimpangan harga.
Strategi perdagangan pasangan bergantung pada korelasi sejarah antara harga dua mata wang digital. Apabila harga dua mata wang menunjukkan korelasi yang kuat, trend harga mereka umumnya selaras. Jika nisbah harga antara kedua-dua menyimpang dengan ketara pada saat tertentu, ia boleh dianggap sebagai kelainan sementara dan harga akan cenderung kembali ke tahap normal. Pasaran mata wang digital sangat saling berkaitan. Apabila mata wang digital utama (seperti Bitcoin) turun naik dengan ketara, ia biasanya akan mencetuskan tindak balas yang diselaraskan dalam mata wang digital lain. Sesetengah mata wang mungkin mempunyai korelasi positif yang sangat jelas yang boleh berlangsung kerana institusi pelaburan yang sama, pembuat pasaran yang sama, dan trek yang sama. Sesetengah mata wang berkorelasi negatif, tetapi terdapat lebih sedikit mata wang yang berkorelasi negatif, dan kerana mereka semua dipengaruhi oleh trend pasaran, mereka sering akan mempunyai trend pasaran yang konsisten.
Misalkan mata wang A dan mata wang B mempunyai korelasi harga yang tinggi. Pada masa tertentu, nilai purata nisbah harga A / B adalah 1. Jika pada masa tertentu, nisbah harga A / B menyimpang lebih daripada 0.001, iaitu lebih daripada 1.001, maka anda boleh berdagang dengan cara berikut: Buka kedudukan panjang pada B dan buka kedudukan pendek pada A. Sebaliknya, apabila nisbah harga A / B lebih rendah daripada 0.999: Buka kedudukan panjang pada A dan buka kedudukan pendek pada B.
Kunci keuntungan terletak pada keuntungan spread apabila harga menyimpang dari purata dan kembali normal.
Kod ini boleh digunakan secara langsung. Adalah lebih baik untuk memuat turun Anancoda dan debugnya di buku nota Jupyer. Ia termasuk pakej untuk analisis data yang biasa 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 sejarah kontrak kekal pasangan dagangan yang ditentukan dari bursa Binance dan menyimpan data dalam Pandas DataFrame. Data K-line termasuk maklumat seperti harga pembukaan, harga tertinggi, harga terendah, harga penutupan, dan jumlah dagangan. Kali ini kami terutamanya 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 agak besar. Untuk memuat turun lebih cepat, hanya data K-line sejam tiga bulan yang lalu diperoleh. df_close mengandungi data harga penutupan semua mata wang.
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')
Kita tentukan 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)
Pengiraan korelasi adalah kaedah dalam statistik yang digunakan untuk mengukur hubungan linear antara dua pembolehubah. Kaedah pengiraan korelasi yang paling biasa digunakan adalah pekali korelasi Pearson. Berikut adalah prinsip, formula dan kaedah pelaksanaan pengiraan korelasi. Pekali korelasi Pearson digunakan untuk mengukur hubungan linear antara dua pembolehubah dan julat nilainya adalah antara -1 dan 1:
Gabungan korelasi Pearson menentukan korelasi antara dua pembolehubah dengan mengira kovarian dan penyimpangan standard mereka. Rumusnya adalah seperti berikut:
di mana:
Sudah tentu, anda tidak perlu terlalu bimbang tentang bagaimana ia dikira. Anda boleh menggunakan 1 baris kod di Python untuk mengira korelasi semua mata wang. Rajah menunjukkan peta haba korelasi. Merah mewakili korelasi positif, biru mewakili korelasi negatif, dan semakin gelap warnanya, semakin kuat korelasinya. Anda dapat melihat bahawa sebahagian besar kawasan adalah merah gelap, jadi korelasi positif mata wang 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 wang teratas yang paling berkorelasi dipilih. Hasilnya adalah seperti berikut. Korelasi mereka sangat kuat, semua di atas 0.99.
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
Kod yang sepadan adalah seperti 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)
Kod backtest khusus adalah seperti berikut. Strategi demonstrasi terutamanya memerhatikan nisbah harga dua mata wang kripto (IOTA dan ZIL) dan berdagang mengikut perubahan dalam nisbah ini. Langkah-langkah tertentu adalah seperti berikut:
e
dengan baki awal $ 10,000 dan yuran transaksi 0.02%.avg
.value = 1000
.df_close
.diff
.aim_value
, dan satu nilai diperdagangkan untuk setiap penyimpangan 0.01.pair_a
dan belipair_b
operations.pair_a
dan jualpair_b
operasi dilakukan.avg
untuk mencerminkan nisbah harga terkini.res_list
.res_list
kepada bingkai datares
untuk analisis dan persembahan 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);
Secara keseluruhan 4 kumpulan mata wang telah diuji semula, dan hasilnya adalah ideal. Pengiraan korelasi semasa menggunakan data masa depan, jadi ia tidak sangat tepat. Artikel ini juga membahagikan data kepada dua bahagian, berdasarkan pengiraan korelasi sebelumnya dan perdagangan backtest berikutnya. Hasilnya sedikit berbeza tetapi tidak buruk. Kami biarkan pengguna untuk berlatih dan mengesahkan.
Walaupun strategi perdagangan pasangan boleh menguntungkan dalam teori, masih ada beberapa risiko dalam operasi sebenar: korelasi antara mata wang boleh berubah dari masa ke masa, menyebabkan strategi gagal; di bawah keadaan pasaran yang melampau, penyimpangan harga boleh meningkat, mengakibatkan kerugian yang lebih besar; kecairan yang rendah dari mata wang tertentu boleh membuat transaksi sukar untuk dilaksanakan atau meningkatkan kos; dan yuran yang dihasilkan oleh transaksi yang kerap boleh mengikis keuntungan.
Untuk mengurangkan risiko dan meningkatkan kestabilan strategi, langkah-langkah penambahbaikan berikut boleh dipertimbangkan: mengira semula korelasi antara mata wang dan menyesuaikan pasangan dagangan dengan tepat pada masanya; menetapkan titik stop loss dan mengambil keuntungan untuk mengawal kerugian maksimum satu transaksi; berdagang beberapa pasangan mata wang pada masa yang sama untuk mempelbagaikan risiko.
Strategi perdagangan pasangan mata wang digital mencapai keuntungan dengan memanfaatkan korelasi harga mata wang dan melakukan operasi arbitrase apabila harga menyimpang. Strategi ini mempunyai kelayakan teori yang tinggi. Kod sumber strategi perdagangan langsung yang mudah berdasarkan strategi ini akan dikeluarkan kemudian. Jika anda mempunyai lebih banyak soalan atau memerlukan perbincangan lanjut, sila hubungi kami.