2021 está llegando a su fin, y los puntos calientes de DEFI a GAMEFI están surgiendo en una corriente interminable, y el mercado general sigue siendo un mercado alcista. Ahora mire hacia atrás y resuma, ¿cuánto ganó en 2021? ¿Qué oportunidades perdió? ¿Cuáles fueron algunas inversiones exitosas? Recientemente, eché un vistazo al mercado histórico del año pasado y encontré una estrategia de lucro inesperada y simple, que es un índice multidivisas.
Hay tantas monedas en el intercambio, muchas de las cuales están destinadas a ser desconocidas e incluso pueden retirarse del comercio. Aquí elegimos la moneda de Binance perpetual contract que se han utilizado en el mercado. Generalmente se prueban y reconocen como monedas convencionales, que son relativamente seguras. Después de una simple detección, se eliminaron algunas monedas de índice y finalmente se obtuvieron 134 monedas.
En [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
En [144]:
## Current trading pairs
Info = requests.get('https://fapi.binance.com/fapi/v1/exchangeInfo')
symbols = [s['symbol'] for s in Info.json()['symbols']]
En [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)
En [155]:
print(len(symbols_f))
Luego obtenemos sus precios de cierre diarios para el año pasado, observando que algunas monedas han estado en el estante durante un corto período de tiempo, por lo que necesitamos rellenar los datos.
El rendimiento del índice final es de aproximadamente 12 veces, es decir, si usted compra las 134 monedas el 1 de enero de 2021 en promedio, el rendimiento final de no hacer nada será de 12 veces. Se estima que más del 90% de los comerciantes no superan el índice promedio. Entre ellos, las monedas con la mayor caída son: ICP cayó en 93%, DODO cayó en 85% y LINA cayó en 75%. Mientras que SOL, FTM, LUNA, MATIC, SAND y AXS han aumentado casi 100 veces. Entre ellos, AXS subió 168 veces, convirtiéndose en el caballo oscuro más grande. La mediana aumentó 3 veces, lo que fue impulsado principalmente por la cadena pública y los juegos. Para evitar el sesgo de supervivencia, excluimos la nueva moneda perpetua durante el período, y también logramos casi 11 veces los beneficios. Es 7 veces los beneficios de BTC para sobrevivir.
Esta es una tasa de rendimiento desesperada. He trabajado duro para hacer todo tipo de estrategias, pero estaba lejos de las ganancias de no hacer nada en un año. Sin embargo, debe tenerse en cuenta que algunos de los aumentos específicos son demasiado grandes y se desvió del índice obviamente. Si estas monedas no se seleccionan al principio del año, las ganancias estarán cerca de la mediana, que es mucho menos rentable.
En [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
En [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
En el [165]:
df_all_s.tail() #data structure
Fuera [1]:
En [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
Fuera [1]:
En el [175]:
#The median increase
df_norm.median(axis=1).plot(figsize=(12,4),grid=True);
Fuera [1]:
En [168]:
#Ranking for increase/decrease
print(df_norm.iloc[-1].round(2).sort_values().to_dict())
En [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())
En [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
En [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);
Fuera[208]:
En [212]:
#Compared with Bitcoin
(df.mean(axis=1)/df.BTCUSDT).plot(figsize=(12,4),grid=True);
Fuera [1]:
En [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)
En el [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
En el [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);
Fuera[419]:
En el backtest, se seleccionaron todas las monedas del contrato perpetuo Binance en línea el 1 de enero de 2021. El período de la línea K fue de 1h. El parámetro comenzó a escalar en posiciones cuando la posición era un 5% inferior al promedio, y las vendió cuando la posición era más del 5%. Cuando el backtest es todas las monedas, el rendimiento estratégico final es de 7.7 veces. Obviamente no es tan bueno como el rendimiento promedio de 13 veces. Esto también se espera. Después de todo, varias monedas que subieron cien veces son demasiado especiales, y la estrategia de equilibrio las venderá a todas.
Si se eliminan de la prueba de retroceso las 10 monedas con mayor aumento, sólo se considerarán las monedas relativamente mediocres, y el ingreso final será de 4,8 veces, muy superior al rendimiento promedio de 3,4 veces.
Si solo se rotan las 3 monedas con mayor aumento, las ganancias finales serán 373 veces, lo que es mucho más que el rendimiento promedio de 160 veces. Esto muestra que si la tendencia y el aumento de la moneda rotada seleccionada tienden a ser consistentes, el resultado de rotar será mucho mejor que el de no hacer nada.
En el [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)
En el [495]:
e.account['USDT']
Fuera[495]:
En el [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);
Fuera[496]:
En el [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)
En el [501]:
e.account['USDT']
Fuera[501]:
En [499]:
(res.total/10000).plot(figsize=(12,4),grid = True);
df[symbols].mean(axis=1).plot(figsize=(12,4),grid=True);
En el caso de las empresas de servicios de telecomunicaciones:
En el [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)
En el [504]:
e.account['USDT']
Fuera[504]:
En el [505]:
(res.total/10000).plot(figsize=(12,4),grid = True);
df[symbols].mean(axis=1).plot(figsize=(12,4),grid=True);
Fuera[505]:
En general, 2021 será un mercado alcista para las monedas falsificadas y un año a la baja para Bitcoin. El valor de mercado de Bitcoin ha caído al 40% ahora desde el 70% al comienzo del año, que es el nivel más bajo de la historia. Por lo tanto, las ganancias promedio de comprar y mantener bienes falsificados en el año pasado son mucho más altas que las de mantener Bitcoin. Mirando hacia adelante a 2022, si considera que todavía habrá varias monedas centenarias en el mercado actual en el futuro, puede diversificar sus posiciones con audacia y esperar pacientemente. Si es particularmente optimista sobre algunas monedas o el mercado promedio, puede usar la estrategia rotativa para obtener rendimientos excesivos sin pensar. Si piensa que las cosas llegarán una contra otra cuando se vuelvan al extremo, puede cazar Bitcoin para obtener mejores rendimientos y seguridad.