Gần đây, tôi đã thấy nhật ký định lượng của BuOu
Giao dịch cặp tiền kỹ thuật số là một chiến lược giao dịch dựa trên sự điều chỉnh thống kê, đồng thời mua và bán hai loại tiền điện tử tương quan cao để có được lợi nhuận từ độ lệch giá. Bài viết này sẽ giới thiệu các nguyên tắc của chiến lược này, cơ chế lợi nhuận, phương pháp lựa chọn tiền tệ, rủi ro tiềm ẩn và cách cải thiện chúng, và cung cấp một số ví dụ mã Python thực tế.
Các chiến lược giao dịch cặp dựa trên mối tương quan lịch sử giữa giá của hai loại tiền kỹ thuật số. Khi giá của hai loại tiền cho thấy mối tương quan mạnh mẽ, xu hướng giá của chúng thường đồng bộ. Nếu tỷ lệ giá giữa hai loại tiền chênh lệch đáng kể tại một thời điểm nhất định, nó có thể được coi là một sự bất thường tạm thời và giá sẽ có xu hướng trở lại mức bình thường. Thị trường tiền kỹ thuật số có sự kết nối chặt chẽ. Khi một loại tiền kỹ thuật số lớn (như Bitcoin) dao động đáng kể, nó thường sẽ kích hoạt một phản ứng phối hợp trong các loại tiền kỹ thuật số khác. Một số loại tiền có thể có một mối tương quan tích cực rất rõ ràng có thể kéo dài do các tổ chức đầu tư tương tự, các nhà tạo thị trường tương tự và cùng một theo dõi. Một số loại tiền có mối tương quan tiêu cực, nhưng có ít loại tiền tương quan tiêu cực hơn, và vì tất cả chúng đều bị ảnh hưởng bởi xu hướng thị trường, chúng thường sẽ có xu hướng thị trường nhất quán.
Giả sử rằng tiền tệ A và tiền tệ B có mối tương quan giá cao. Tại một thời điểm nhất định, giá trị trung bình của tỷ lệ giá A/B là 1. Nếu tại một thời điểm nhất định, tỷ lệ giá A/B lệch hơn 0,001, tức là hơn 1,001, thì bạn có thể giao dịch theo các cách sau: Mở vị trí dài trên B và mở vị trí ngắn trên A. Ngược lại, khi tỷ lệ giá A/B thấp hơn 0,999: Mở vị trí dài trên A và mở vị trí ngắn trên B.
Chìa khóa cho lợi nhuận nằm ở lợi nhuận chênh lệch khi giá lệch so với mức trung bình và trở lại bình thường.
Các mã này có thể được sử dụng trực tiếp. Tốt nhất là tải về Anancoda và gỡ lỗi nó trong sổ tay Jupyer. Nó bao gồm các gói để phân tích dữ liệu thường được sử dụng trực tiếp.
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
Chức năng chính của chức năng GetKlines là lấy dữ liệu K-line lịch sử của hợp đồng vĩnh cửu cặp giao dịch được chỉ định từ sàn giao dịch Binance và lưu trữ dữ liệu trong Pandas DataFrame. Dữ liệu K-line bao gồm thông tin như giá mở cửa, giá cao nhất, giá thấp nhất, giá đóng cửa và khối lượng giao dịch.
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
Số lượng dữ liệu tương đối lớn. Để tải xuống nhanh hơn, chỉ có dữ liệu K-line hàng giờ của ba tháng qua. df_close chứa dữ liệu giá đóng của tất cả các loại tiền tệ.
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')
Chúng ta xác định một đối tượng trao đổi cho backtest sau.
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)
Tính toán tương quan là một phương pháp trong thống kê được sử dụng để đo mối quan hệ tuyến tính giữa hai biến. Phương pháp tính toán tương quan được sử dụng phổ biến nhất là hệ số tương quan Pearson. Sau đây là nguyên tắc, công thức và phương pháp thực hiện tính toán tương quan.
Các hệ số tương quan Pearson xác định sự tương quan giữa hai biến bằng cách tính toán covariance và độ lệch chuẩn của chúng. công thức là như sau:
trong đó:
Tất nhiên, bạn không cần phải lo lắng quá nhiều về cách tính toán. Bạn có thể sử dụng 1 dòng mã trong Python để tính toán mối tương quan của tất cả các loại tiền tệ. Hình này cho thấy một bản đồ nhiệt tương quan. Màu đỏ đại diện cho mối tương quan tích cực, màu xanh dương đại diện cho mối tương quan âm, và màu sắc tối hơn, mối tương quan càng mạnh. Bạn có thể thấy rằng hầu hết khu vực là màu đỏ đậm, vì vậy mối tương quan tích cực của tiền kỹ thuật số rất mạnh.
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);
Dựa trên mối tương quan, 20 cặp tiền tệ có mối tương quan cao nhất được chọn. Kết quả là như sau. Sự tương quan của chúng rất mạnh, tất cả đều trên 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
Mã tương ứng là như sau:
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)
Mã backtest cụ thể là như sau. Chiến lược trình diễn chủ yếu quan sát tỷ lệ giá của hai loại tiền điện tử (IOTA và ZIL) và giao dịch theo những thay đổi trong tỷ lệ này. Các bước cụ thể là như sau:
e
với số dư ban đầu là $10,000 và phí giao dịch là 0.02%.avg
.value = 1000
.df_close
.diff
.aim_value
Các giao dịch mua và bán được xác định dựa trên vị trí tài khoản vãng lai và tình hình giá.pair_a
và muapair_b
operations.pair_a
và bánpair_b
các hoạt động được thực hiện.avg
để phản ánh tỷ lệ giá mới nhất.res_list
.res_list
đến khung dữ liệures
để phân tích và trình bày thêm.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);
Tổng cộng 4 nhóm tiền tệ đã được kiểm tra lại, và kết quả là lý tưởng. Việc tính toán tương quan hiện tại sử dụng dữ liệu tương lai, vì vậy nó không chính xác lắm. Bài viết này cũng chia dữ liệu thành hai phần, dựa trên tính toán tương quan trước đó và giao dịch kiểm tra lại tiếp theo. Kết quả hơi khác nhau nhưng không tệ. Chúng tôi để cho người dùng thực hành và xác minh.
Mặc dù chiến lược giao dịch cặp có thể có lợi về mặt lý thuyết, nhưng vẫn có một số rủi ro trong hoạt động thực tế: mối tương quan giữa các loại tiền tệ có thể thay đổi theo thời gian, khiến chiến lược thất bại; trong điều kiện thị trường cực đoan, độ lệch giá có thể tăng lên, dẫn đến tổn thất lớn hơn; thanh khoản thấp của một số loại tiền tệ có thể làm cho các giao dịch khó thực hiện hoặc tăng chi phí; và phí tạo ra bởi các giao dịch thường xuyên có thể làm xói mòn lợi nhuận.
Để giảm rủi ro và cải thiện sự ổn định của các chiến lược, các biện pháp cải thiện sau đây có thể được xem xét: thường xuyên tính lại mối tương quan giữa các loại tiền tệ và điều chỉnh các cặp giao dịch kịp thời; đặt điểm dừng lỗ và lấy lợi nhuận để kiểm soát lỗ tối đa của một giao dịch duy nhất; giao dịch nhiều cặp tiền tệ cùng một lúc để đa dạng hóa rủi ro.
Chiến lược giao dịch cặp tiền kỹ thuật số đạt được lợi nhuận bằng cách tận dụng lợi thế của mối tương quan giữa giá tiền tệ và thực hiện các hoạt động điều chỉnh khi giá lệch. Chiến lược này có khả năng thực hiện lý thuyết cao. Mã nguồn chiến lược giao dịch trực tiếp đơn giản dựa trên chiến lược này sẽ được phát hành sau này. Nếu bạn có thêm câu hỏi hoặc cần thảo luận thêm, vui lòng cảm thấy miễn phí để giao tiếp.