2021 hampir berakhir, dan titik panas dari DEFI ke GAMEFI muncul dalam aliran yang tidak berkesudahan, dan pasaran keseluruhan masih merupakan pasaran lembu. Sekarang lihat kembali dan rangkum, berapa banyak yang anda peroleh pada tahun 2021? Peluang apa yang anda lewatkan? Apakah beberapa pelaburan yang berjaya? Baru-baru ini, saya melihat pasaran bersejarah tahun lalu dan menemui strategi keuntungan yang tidak dijangka, iaitu indeks pelbagai mata wang.
Terdapat begitu banyak mata wang di bursa, banyak di antaranya ditakdirkan tidak diketahui dan mungkin juga ditarik balik dari perdagangan. Di sini kita memilih mata wang kontrak kekal Binance yang telah digunakan di pasaran. Mereka biasanya diuji dan diiktiraf sebagai mata wang arus perdana, yang agak selamat. Selepas pemeriksaan mudah, beberapa mata wang indeks dikeluarkan dan 134 mata wang akhirnya diperoleh.
Dalam [1]:
import requests
from datetime import date,datetime
import time
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
Dalam [144]:
## Current trading pairs
Info = requests.get('https://fapi.binance.com/fapi/v1/exchangeInfo')
symbols = [s['symbol'] for s in Info.json()['symbols']]
Di [154]:
symbols_f = list(set(filter(lambda x: x[-4:] == 'USDT', [s.split('_')[0] for s in symbols]))-
set(['1000SHIBUSDT','1000XECUSDT','BTCDOMUSDT','DEFIUSDT','BTCSTUSDT'])) + ['SHIBUSDT','XECUSDT']
print(symbols_f)
Di [155]:
print(len(symbols_f))
Kami kemudian mendapatkan harga penutupan harian mereka untuk tahun lepas, mencatat bahawa beberapa mata wang telah berada di rak untuk tempoh yang singkat, jadi kita perlu mengisi data. indeks boleh dikira dengan menormalkan data.
Pengembalian indeks akhir adalah kira-kira 12 kali, iaitu, jika anda membeli 134 syiling pada 1 Januari 2021 secara purata, pengembalian akhir tidak melakukan apa-apa akan menjadi 12 kali. Dianggarkan bahawa lebih daripada 90% peniaga tidak melebihi indeks purata. Di antara mereka, mata wang dengan penurunan terbesar adalah: ICP jatuh sebanyak 93%, DODO jatuh sebanyak 85%, dan LINA jatuh sebanyak 75%. Sementara SOL, FTM, LUNA, MATIC, SAND dan AXS telah meningkat hampir 100 kali. Di antara mereka, AXS meningkat 168 kali, menjadikannya kuda hitam terbesar. Median meningkat sebanyak 3 kali, yang terutama didorong oleh rantaian awam dan permainan.
Ini adalah kadar pulangan yang putus asa. Saya telah bekerja keras untuk membuat semua jenis strategi, tetapi ia adalah jauh dari keuntungan tidak melakukan apa-apa dalam setahun. Walau bagaimanapun, perlu diperhatikan bahawa beberapa peningkatan tertentu terlalu besar dan ia menyimpang dari indeks jelas. Jika mata wang ini tidak dipilih pada awal tahun, keuntungan akan dekat dengan median, yang jauh kurang menguntungkan.
Di [157]:
#Obtain the function of K-line in any period
def GetKlines(symbol='BTCUSDT',start='2020-8-10',end='2021-8-10',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 = int(time.mktime(datetime.strptime(end, "%Y-%m-%d").timetuple()))*1000 + 8*60*60*1000
intervel_map = {'m':60*1000,'h':60*60*1000,'d':24*60*60*1000}
while start_time < end_time:
mid_time = min(start_time+1000*int(period[:-1])*intervel_map[period[-1]],end_time)
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]
Klines += res_list
elif type(res_list) == list:
start_time = start_time+1000*int(period[:-1])*intervel_map[period[-1]]
else:
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
Dalam [164]:
df_all_s = pd.DataFrame(index=pd.date_range(start='2021-1-1', end='2021-12-28', freq='1d'),columns=symbols_s)
for i in range(len(symbols_f)):
#print(symbols_s[i])
symbol_s = symbols_f[i]
df_s = GetKlines(symbol=symbol_s,start='2021-1-1',end='2021-12-28',period='1d',base='api',v='v3')
df_all_s[symbol_s] = df_s[~df_s.index.duplicated(keep='first')].close
Dalam [165]:
df_all_s.tail() #data structure
Keluar[165]:
Dalam [174]:
df_all = df_all_s.fillna(method='bfill')#filled data
df_norm = df_all/df_all.iloc[0] #normalization
df_norm.mean(axis=1).plot(figsize=(12,4),grid=True);
#The final index return chart
Keluar [1]:
Dalam [175]:
#The median increase
df_norm.median(axis=1).plot(figsize=(12,4),grid=True);
Keluar[175]:
Dalam [168]:
#Ranking for increase/decrease
print(df_norm.iloc[-1].round(2).sort_values().to_dict())
Dalam [317]:
#Maximum rollback of current price compared with the highest point in the year
print((1-df_norm.iloc[-1]/df_norm.max()).round(2).sort_values().to_dict())
Dalam [177]:
df_all_f = pd.DataFrame(index=pd.date_range(start='2021-1-1', end='2021-12-28', freq='1d'),columns=symbols_s)
for i in range(len(symbols_f)):
#print(symbols_s[i])
symbol_f = symbols_f[i]
df_f = GetKlines(symbol=symbol_f,start='2021-1-1',end='2021-12-28',period='1d',base='fapi',v='v1')
df_all_f[symbol_f] = df_f[~df_f.index.duplicated(keep='first')].close
Dalam [208]:
#Excluding new currency
df = df_all_s[df_all_s.columns[~df_all_f.iloc[0].isnull()]]
df = df.fillna(method='bfill')
df = df/df.iloc[0]
df.mean(axis=1).plot(figsize=(12,4),grid=True);
Keluar[208]:
Dalam [212]:
#Compared with Bitcoin
(df.mean(axis=1)/df.BTCUSDT).plot(figsize=(12,4),grid=True);
Keluar[212]:
Dalam [213]:
#Use the original backtest engine
class Exchange:
def __init__(self, trade_symbols, fee=0.0004, 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}}
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 #Deduct the handling 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 #Profits
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
for symbol in self.trade_symbols:
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'] = abs(self.account[symbol]['amount'])*close_price[symbol]
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)
Dalam [418]:
#The hourly K-line was taken to make the backtest more accurate
df_all_s = pd.DataFrame(index=pd.date_range(start='2021-1-1', end='2021-12-28', freq='1h'),columns=symbols_s)
for i in range(len(symbols_f)):
#print(symbols_s[i])
symbol_s = symbols_f[i]
df_s = GetKlines(symbol=symbol_s,start='2021-1-1',end='2021-12-28',period='1h',base='api',v='v3')
df_all_s[symbol_s] = df_s[~df_s.index.duplicated(keep='first')].close
Dalam [419]:
df = df_all_s[df_all_s.columns[~df_all_f.iloc[0].isnull()]]
df = df.fillna(method='bfill')
df = df/df.iloc[0]
df.mean(axis=1).plot(figsize=(12,4),grid=True);
Keluar[419]:
Dalam backtest, semua mata wang kontrak kekal Binance dalam talian pada 1 Januari 2021 dipilih. Tempoh K-line adalah 1h. Parameter mula skala dalam kedudukan apabila kedudukan 5% lebih rendah daripada purata, dan menjualnya apabila kedudukan lebih daripada 5%. Apabila backtest adalah semua mata wang, pulangan strategik akhir adalah 7.7 kali. Jelas tidak begitu baik dengan pulangan purata 13 kali. Ini juga diharapkan. Lagipun, beberapa mata wang yang naik seratus kali terlalu istimewa, dan strategi baki akan menjualnya semua.
Jika 10 mata wang dengan kenaikan tertinggi dikeluarkan dari backtest, hanya mata wang yang agak biasa akan dipertimbangkan, dan pendapatan akhir akan menjadi 4.8 kali, jauh melebihi prestasi purata 3.4 kali.
Jika hanya 3 mata wang dengan kenaikan tertinggi berputar, keuntungan akhir akan menjadi 373 kali, yang jauh lebih banyak daripada prestasi purata 160 kali. Ini menunjukkan bahawa jika trend dan peningkatan mata wang berputar yang dipilih cenderung konsisten, hasil berputar akan jauh lebih baik daripada tidak melakukan apa-apa.
Dalam [494]:
#Full currency backtest
symbols = list(df.iloc[-1].sort_values()[:].index)
e = Exchange(symbols, fee=0.001, initial_balance=10000)
res_list = []
avg_pct = 1/len(symbols)
for row in df[symbols].iterrows():
prices = row[1]
total = e.account['USDT']['total']
e.Update(prices)
for symbol in symbols:
pct = e.account[symbol]['value']/total
if pct < 0.95*avg_pct:
e.Buy(symbol,prices[symbol],(avg_pct-pct)*total/prices[symbol])
if pct > 1.05*avg_pct:
e.Sell(symbol,prices[symbol],(pct-avg_pct)*total/prices[symbol])
res_list.append([e.account[symbol]['value'] for symbol in symbols] + [e.account['USDT']['total']])
res = pd.DataFrame(data=res_list, columns=symbols+['total'],index = df.index)
Dalam [495]:
e.account['USDT']
Keluar[495]:
Dalam [496]:
# Backtest performance of full currencies
(res.total/10000).plot(figsize=(12,4),grid = True);
df[symbols].mean(axis=1).plot(figsize=(12,4),grid=True);
Keluar[496]:
Dalam [498]:
#Remove currencies with huge growth
symbols = list(df.iloc[-1].sort_values()[:-10].index)
e = Exchange(symbols, fee=0.001, initial_balance=10000)
res_list = []
avg_pct = 1/len(symbols)
for row in df[symbols].iterrows():
prices = row[1]
total = e.account['USDT']['total']
e.Update(prices)
for symbol in symbols:
pct = e.account[symbol]['value']/total
if pct < 0.95*avg_pct:
e.Buy(symbol,prices[symbol],(avg_pct-pct)*total/prices[symbol])
if pct > 1.05*avg_pct:
e.Sell(symbol,prices[symbol],(pct-avg_pct)*total/prices[symbol])
res_list.append([e.account[symbol]['value'] for symbol in symbols] + [e.account['USDT']['total']])
res = pd.DataFrame(data=res_list, columns=symbols+['total'],index = df.index)
Dalam [501]:
e.account['USDT']
Keluar[501]:
Dalam [499]:
(res.total/10000).plot(figsize=(12,4),grid = True);
df[symbols].mean(axis=1).plot(figsize=(12,4),grid=True);
Keluar [499]:
Dalam [503]:
#Only the currency with the highest increase is tested
symbols = list(df.iloc[-1].sort_values()[-3:].index)
e = Exchange(symbols, fee=0.001, initial_balance=10000)
res_list = []
avg_pct = 1/len(symbols)
for row in df[symbols].iterrows():
prices = row[1]
total = e.account['USDT']['total']
e.Update(prices)
for symbol in symbols:
pct = e.account[symbol]['value']/total
if pct < 0.95*avg_pct:
e.Buy(symbol,prices[symbol],(avg_pct-pct)*total/prices[symbol])
if pct > 1.05*avg_pct:
e.Sell(symbol,prices[symbol],(pct-avg_pct)*total/prices[symbol])
res_list.append([e.account[symbol]['value'] for symbol in symbols] + [e.account['USDT']['total']])
res = pd.DataFrame(data=res_list, columns=symbols+['total'],index = df.index)
Dalam [504]:
e.account['USDT']
Keluar[504]:
Dalam [505]:
(res.total/10000).plot(figsize=(12,4),grid = True);
df[symbols].mean(axis=1).plot(figsize=(12,4),grid=True);
Keluar[505]:
Secara umum, 2021 akan menjadi pasaran bull untuk duit syiling palsu dan tahun penurunan untuk Bitcoin. Nilai pasaran Bitcoin telah jatuh kepada 40% sekarang dari 70% pada awal tahun, yang merupakan tahap terendah dalam sejarah. Oleh itu, keuntungan purata dari membeli dan memegang barang palsu pada tahun lalu jauh lebih tinggi daripada memegang Bitcoin. Menunggu ke hadapan ke 2022, jika anda menganggap masih akan ada beberapa ratus mata wang di pasaran semasa pada masa depan, anda boleh mempelbagaikan kedudukan anda dengan berani dan menunggu dengan sabar. Jika anda sangat optimis tentang beberapa mata wang atau pasaran purata, anda boleh menggunakan strategi berputar untuk mendapatkan pulangan yang berlebihan tanpa berfikir. Jika anda fikir perkara akan mencapai satu sama lain apabila mereka berbalik melampau, anda boleh memburu Bitcoin untuk mendapatkan pulangan dan keselamatan yang lebih baik.