2021 está chegando ao fim, e os hotspots do DEFI ao GAMEFI estão surgindo em um fluxo interminável, e o mercado geral ainda é um mercado alcista. Agora olhe para trás e resuma, quanto você ganhou em 2021? Que oportunidades você perdeu? Quais foram alguns investimentos bem-sucedidos? Recentemente, eu dei uma olhada no mercado histórico do ano passado e encontrei uma estratégia de lucro inesperada e simples, que é um índice multi-moeda.
Há muitas moedas na bolsa, muitas das quais estão destinadas a ser desconhecidas e podem até ser retiradas da negociação. Aqui escolhemos a moeda do contrato perpétuo da Binance que foram usadas no mercado. Eles são geralmente testados e reconhecidos como moedas convencionais, que são relativamente seguras. Após uma simples triagem, algumas moedas do índice foram removidas e 134 moedas foram obtidas finalmente.
Em [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
Em [144]:
## Current trading pairs
Info = requests.get('https://fapi.binance.com/fapi/v1/exchangeInfo')
symbols = [s['symbol'] for s in Info.json()['symbols']]
Em [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)
Em [155]:
print(len(symbols_f))
Em seguida, obtemos seus preços de fechamento diários para o ano passado, observando que algumas moedas foram na prateleira por um curto período de tempo, por isso precisamos preencher os dados.
O retorno final do índice é de cerca de 12 vezes, ou seja, se você comprar as 134 moedas em 1o de janeiro de 2021, em média, o retorno final de não fazer nada será de 12 vezes. Estima-se que mais de 90% dos comerciantes não superam o índice médio. Entre eles, as moedas com maior queda são: ICP caiu 93%, DODO caiu 85% e LINA caiu 75%. Enquanto SOL, FTM, LUNA, MATIC, SAND e AXS aumentaram quase 100 vezes. Entre eles, o AXS subiu 168 vezes, tornando-se o maior cavalo negro. A mediana aumentou 3 vezes, que foi principalmente impulsionada pela cadeia pública e jogos. A fim de evitar o viés de sobrevivência, excluímos a nova moeda perpétua durante o período, e também alcançamos quase 11 vezes o lucro. É 7 vezes o lucro do BTC para sobrevivência.
Esta é uma taxa de retorno desesperadora. Eu trabalhei duro para fazer todos os tipos de estratégias, mas estava longe dos lucros de não fazer nada em um ano. No entanto, deve-se notar que alguns dos aumentos específicos são muito grandes e foi desviado do índice obviamente. Se essas moedas não forem selecionadas no início do ano, os lucros estarão próximos da mediana, que é muito menos lucrativo.
Em [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
Em [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
Em [165]:
df_all_s.tail() #data structure
Fora[165]:
Em [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
Fora [1]:
Em [175]:
#The median increase
df_norm.median(axis=1).plot(figsize=(12,4),grid=True);
Fora [1]:
Em [168]:
#Ranking for increase/decrease
print(df_norm.iloc[-1].round(2).sort_values().to_dict())
Em [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())
Em [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
Em [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);
Fora[208]:
Em [212]:
#Compared with Bitcoin
(df.mean(axis=1)/df.BTCUSDT).plot(figsize=(12,4),grid=True);
Fora[212]:
Em [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)
Em [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
Em [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);
Fora[419]:
No backtest, todas as moedas do contrato perpétuo Binance on-line em 1o de janeiro de 2021 foram selecionadas. O período de linha K foi de 1h. O parâmetro começou a escalar em posições quando a posição era 5% menor que a média, e vendê-las quando a posição era superior a 5%. Quando o backtest é todas as moedas, o retorno estratégico final é de 7,7 vezes. Obviamente, não é tão bom quanto o retorno médio de 13 vezes. Isso também é esperado. Afinal, várias moedas que subiram cem vezes são muito especiais, e a estratégia de equilíbrio as venderá todas.
Se as 10 moedas com o maior aumento forem removidas do backtest, só serão consideradas as moedas relativamente medíocres e o rendimento final será de 4,8 vezes, muito superior ao desempenho médio de 3,4 vezes.
Se apenas as 3 moedas com o maior aumento forem rotadas, os lucros finais serão 373 vezes, o que é muito mais do que o desempenho médio de 160 vezes.
Em [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)
Em [495]:
e.account['USDT']
Fora[495]:
Em [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);
Fora[496]:
Em [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)
Em [501]:
e.account['USDT']
Fora[501]:
Em [499]:
(res.total/10000).plot(figsize=(12,4),grid = True);
df[symbols].mean(axis=1).plot(figsize=(12,4),grid=True);
Out[499]:
Em [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)
Em [504]:
e.account['USDT']
Fora[504]:
Em [505]:
(res.total/10000).plot(figsize=(12,4),grid = True);
df[symbols].mean(axis=1).plot(figsize=(12,4),grid=True);
Fora[505]:
Em geral, 2021 será um mercado de alta para moedas falsificadas e um ano de queda para o Bitcoin. O valor de mercado do Bitcoin caiu para 40% agora de 70% no início do ano, o que é o nível mais baixo da história. Portanto, os lucros médios de compra e detenção de bens falsificados no ano passado são muito maiores do que o de detenção do Bitcoin. Olhando para frente para 2022, se você considera que ainda haverá várias moedas centenas no mercado atual no futuro, você pode diversificar suas posições com ousadia e esperar pacientemente. Se você é particularmente otimista sobre algumas moedas ou o mercado médio, você pode usar a estratégia giratória para obter retornos excessivos sem pensar.