
Gần đây tôi thấy nhật ký định lượng của Buu có đề cập rằng bạn có thể sử dụng các loại tiền tệ có tương quan tiêu cực để chọn tiền tệ và mở các vị thế để kiếm lợi nhuận dựa trên sự đột phá về chênh lệch giá. Tiền kỹ thuật số về cơ bản có tương quan tích cực và chỉ một số ít tiền có tương quan tiêu cực. Chúng thường có các điều kiện thị trường đặc biệt, chẳng hạn như các điều kiện thị trường độc lập của MEME coin một thời gian trước, hoàn toàn không theo xu hướng của thị trường. Lọc ra những loại tiền tệ này tồn tại lâu dài sau khi đột phá, phương pháp này có thể tạo ra lợi nhuận trong những điều kiện thị trường nhất định. Tuy nhiên, phương pháp phổ biến nhất trong lĩnh vực giao dịch định lượng là sử dụng tương quan dương cho giao dịch cặp. Bài viết này sẽ giới thiệu ngắn gọn về chiến lược này.
Giao dịch cặp tiền điện tử là một chiến lược giao dịch dựa trên chênh lệch giá thống kê, nhằm mục đích kiếm lợi nhuận từ sự chênh lệch giá bằng cách đồng thời mua và bán hai hợp đồng vĩnh viễn tiền điện tử có mối tương quan cao. Bài viết này sẽ giới thiệu các nguyên tắc của chiến lược, cơ chế lợi nhuận, phương pháp sàng lọc tiền tệ, các rủi ro tiềm ẩn và cách cải thiện, đồng thời cung cấp một số ví dụ mã Python thực tế.
Chiến lược giao dịch theo cặp dựa trên mối tương quan lịch sử giữa giá của hai loại tiền điện tử. Khi hai loại tiền tệ có mối tương quan mạnh mẽ, giá của chúng sẽ biến động gần như đồng bộ. Nếu tại một thời điểm nào đó, tỷ lệ giá của hai loại này chênh lệch đáng kể thì có thể coi đây là hiện tượng 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ó tính kết nối cao. Khi một loại tiền kỹ thuật số lớn (như Bitcoin) trải qua những biến động đáng kể, nó thường gây ra phản ứng dây chuyền giữa các loại tiền kỹ thuật số khác. Một số loại tiền tệ có thể có mối tương quan tích cực rất rõ ràng và mối tương quan này có thể được duy trì vì chúng thuộc cùng một tổ chức đầu tư, cùng một nhà tạo lập thị trường và cùng một quỹ đạo. Một số loại tiền tệ có mối tương quan tiêu cực, nhưng có ít loại tiền tệ có mối 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 chung của thị trường nên chúng thường thể hiện xu hướng thị trường nhất quán.
Giả sử đồng tiền A và đồng tiền 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 nào đó, tỷ lệ giá A/B lệch khỏi mức tăng hơn 0,001, tức là hơn 1,001, thì bạn có thể giao dịch theo những cách sau: mở một vị thế mua vào trên B và mở một vị thế bán ra trên A . Ngược lại, khi tỷ lệ giá A/B thấp hơn 0,999: mở một vị thế mua trên A và một vị thế bán trên B.
Chìa khóa để có lợi nhuận nằm ở mức chênh lệch giá khi giá cả biến động và trở lại bình thường. Vì độ lệch giá thường chỉ tồn tại trong thời gian ngắn nên các nhà giao dịch có thể đóng vị thế của mình khi giá trở lại mức trung bình và kiếm lợi nhuận từ sự chênh lệch.
Những mã này có thể được sử dụng trực tiếp, nhưng tốt nhất là tải xuống Anancoda và gỡ lỗi trong máy tính xách tay jupyer. Bao gồm trực tiếp các gói phân tích dữ liệu thường dùng.
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) # 获取所有的正在交易的交易对
Chức năng chính của hàm GetKlines là lấy dữ liệu K-line lịch sử của hợp đồng vĩnh viễn của cặp giao dịch được chỉ định từ sàn giao dịch Binance và lưu trữ dữ liệu này trong Pandas DataFrame. Dữ liệu K-line bao gồm giá mở cửa, giá cao nhất, giá thấp nhất, giá đóng cửa, khối lượng giao dịch và các thông tin khác. Lần này chúng tôi chủ yếu sử dụng dữ liệu giá đóng cửa.
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
Lượng dữ liệu tương đối lớn. Để tải xuống nhanh hơn, chỉ lấy dữ liệu K-line theo giờ trong ba tháng qua. df_close chứa dữ liệu giá đóng cửa cho 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')
Xác định đối tượng Exchange cho backtest sau
class Exchange:
def __init__(self, trade_symbols, fee=0.0002, initial_balance=10000):
self.initial_balance = initial_balance #初始的资产
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 #扣除手续费
self.account['USDT']['fee'] += price*amount*self.fee
self.account[symbol]['fee'] += price*amount*self.fee
if cover_amount > 0: #先平仓
self.account['USDT']['realised_profit'] += -direction*(price - self.account[symbol]['hold_price'])*cover_amount #利润
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): #对资产进行更新
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 lường mối quan hệ tuyến tính giữa hai biến. Phương pháp tính tương quan được sử dụng phổ biến nhất là hệ số tương quan Pearson. Dưới đây là các nguyên tắc, công thức và phương pháp thực hiện để tính toán tương quan. Hệ số tương quan Pearson được sử dụng để đo mối quan hệ tuyến tính giữa hai biến và phạm vi giá trị của nó nằm trong khoảng từ -1 đến 1:
Hệ số tương quan Pearson xác định mối tương quan giữa hai biến bằng cách tính toán hiệp phương sai và độ lệch chuẩn của chúng. Công thức như sau:
[ \rho_{X,Y} = \frac{\text{cov}(X,Y)}{\sigma_X \sigma_Y} ]
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ể tính toán mối tương quan của tất cả các loại tiền tệ chỉ bằng một dòng mã Python. Hình ảnh cho thấy bản đồ nhiệt tương quan. Màu đỏ biểu thị tương quan tích cực, màu xanh biểu thị tương quan tiêu cực và màu càng đậm thì tương quan càng mạnh. Có thể thấy rằng nhiều vùng lớn có màu đỏ sẫm, do đó mối tương quan tích cực của tiền kỹ thuật số là 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ó liên quan nhất sẽ được chọn. Kết quả như sau. Mối 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 như sau:
corr_pairs = corr.unstack()
# 移除自身相关性(即对角线上的值)
corr_pairs = corr_pairs[corr_pairs != 1]
sorted_corr_pairs = corr_pairs.sort_values(kind="quicksort")
# 提取最相关和最不相关的前20个币种对
most_correlated = sorted_corr_pairs.tail(40)[::-2]
print("最相关的前20个币种对:")
print(most_correlated)
Mã kiểm tra ngược cụ thể như sau. Chiến lược demo tập trung vào việc quan sát tỷ lệ giá của hai loại tiền điện tử (IOTA và ZIL) và giao dịch dựa trên những thay đổi trong tỷ lệ này. Các bước cụ thể như sau:
khởi tạo:
e, số dư ban đầu là 10.000 đô la và phí giao dịch là 0,02%.avg。value = 1000。Xử lý dữ liệu giá theo từng lần lặp:
df_close。diff。aim_value, với mỗi độ lệch 0,01, giao dịch một giá trị. Và quyết định các hoạt động mua và bán dựa trên vị thế tài khoản hiện tại và điều kiện giá.pair_a và muapair_b vận hành.pair_a và bánpair_b vận hành.Điều chỉnh trung bình:
avg, để phản ánh tỷ giá mới nhất.Cập nhật Tài khoản và Hồ sơ:
res_list。Kết quả đầu ra:
res_list Chuyển đổi sang 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定义放在评论区
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 có 4 nhóm tiền tệ đã được kiểm tra ngược và kết quả tương đối lý tưởng. Các tính toán tương quan hiện tại sử dụng dữ liệu trong tương lai nê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 mối tương quan được tính toán ở phần trước và các giao dịch được kiểm tra ngược ở phần sau. Kết quả có hơi sai lệch một chút nhưng vẫn khá tốt. Người dùng phải tự mình thực hiện xác minh.

Mặc dù chiến lược giao dịch theo cặp có thể mang lại lợi nhuận trên lý thuyết, nhưng vẫn có một số rủi ro khi thực hiện trên 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 này thất bại; trong điều kiện thị trường khắc nghiệt, độ lệch giá có thể tăng lên, dẫn đến thua lỗ lớn; tính thanh khoản thấp của một số loại tiền tệ có thể khiến giao dịch khó thực hiện hoặc tăng chi phí; phí phát sinh từ các giao dịch thường xuyên có thể làm xói mòn lợi nhuận.
Để giảm thiểu rủi ro và nâng cao tính ổn định của chiến lược, có thể cân nhắc các biện pháp cải thiện sau: thường xuyên tính toán 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; thiết lập điểm dừng lỗ và chốt lời để kiểm soát mức lỗ tối đa của một giao dịch duy nhất; giao dịch nhiều cặp tiền để phân tán 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 mối tương quan giữa giá tiền tệ và thực hiện các hoạt động chênh lệch giá khi giá chênh lệch. Chiến lược này có tính khả thi cao về mặt lý thuyết. Mã nguồn chiến lược thời gian thực đơn giản dựa trên chiến lược này sẽ được phát hành sau. Nếu bạn có thêm câu hỏi hoặc cần thảo luận thêm, vui lòng liên hệ.