2021 год подходит к концу, и горячие точки от DEFI до GAMEFI появляются в бесконечном потоке, а общий рынок все еще является бычьим рынком. Теперь оглянитесь назад и резюмируйте, сколько вы заработали в 2021 году? Какие возможности вы упустили? Каковы были некоторые успешные инвестиции? Недавно я взглянул на исторический рынок прошлого года и нашел неожиданную простую стратегию прибыли, которая является мультивалютным индексом.
На бирже существует так много валют, многие из которых предназначены для неизвестности и могут даже быть изъяты из торговли. Здесь мы выбираем валюту Binance, которая была использована на рынке. Они обычно тестируются и признаются основными валютами, которые относительно безопасны. После простого скрининга некоторые индексные валюты были удалены и 134 валюты были получены.
В [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
В [144]:
## Current trading pairs
Info = requests.get('https://fapi.binance.com/fapi/v1/exchangeInfo')
symbols = [s['symbol'] for s in Info.json()['symbols']]
В [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)
В [155]:
print(len(symbols_f))
Затем мы получаем их ежедневные цены закрытия за последний год, отмечая, что некоторые валюты были на полке в течение короткого периода времени, поэтому нам нужно заполнить данные.
Окончательная доходность индекса составляет около 12 раз, то есть, если вы купите 134 монеты 1 января 2021 года в среднем, конечная доходность от ничего не делать будет в 12 раз. По оценкам, более 90% трейдеров не превосходят средний индекс. Среди них валюты с наибольшим снижением: ICP упал на 93%, DODO упал на 85%, а LINA упал на 75%. В то время как SOL, FTM, LUNA, MATIC, SAND и AXS выросли почти в 100 раз. Среди них AXS вырос в 168 раз, что делает его самой большой темной лошадью. Медиана выросла в 3 раза, что в основном было обусловлено публичной цепочкой и играми. Чтобы избежать предвзятости выживания, мы исключили вечную новую валюту в течение периода, и мы также достигли почти в 11 раз прибыли. Это в 7 раз больше прибыли BTC.
Это отчаянный уровень доходности. Я много работал, чтобы сделать всевозможные стратегии, но это было далеко от прибыли ничего не делать в течение года. Однако следует отметить, что некоторые из конкретных увеличений слишком велики, и это было отклонено от индекса, очевидно. Если эти валюты не выбраны в начале года, прибыль будет близка к медиане, которая намного менее прибыльна.
В [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
В [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
В [165]:
df_all_s.tail() #data structure
Выход[165]:
В [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
Выход[174]:
В [175]:
#The median increase
df_norm.median(axis=1).plot(figsize=(12,4),grid=True);
Выход[175]:
В [168]:
#Ranking for increase/decrease
print(df_norm.iloc[-1].round(2).sort_values().to_dict())
В [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())
В [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
В [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);
Выход[208]:
В [212]:
#Compared with Bitcoin
(df.mean(axis=1)/df.BTCUSDT).plot(figsize=(12,4),grid=True);
Выход[212]:
В [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)
В [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
В [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);
Вне[419]:
В обратном тесте были выбраны все валюты онлайн-вечного контракта Binance 1 января 2021 года. Период K-линии составлял 1h. Параметр начал масштабироваться в позициях, когда позиция была на 5% ниже средней, и продавать их, когда позиция была более 5%. Когда обратный тест - все валюты, конечная стратегическая доходность составляет 7,7 раза. Очевидно, это не так хорошо, как средняя доходность в 13 раз. Это также ожидается. В конце концов, несколько валют, которые выросли в сто раз, слишком особенны, и стратегия баланса продаст их все.
Если 10 валют с наибольшим ростом будут удалены из бэкстеста, будут рассматриваться только относительно посредственные валюты, и конечный доход составит 4,8 раза, что значительно превышает среднюю производительность в 3,4 раза.
Если только 3 валюты с наибольшим ростом будут вращаться, то конечная прибыль составит 373 раза, что намного больше, чем средняя производительность в 160 раз.
В [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)
В [495]:
e.account['USDT']
Выход[495]:
В [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);
Выход[496]:
В [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)
В [501]:
e.account['USDT']
Выход[501]:
В [499]:
(res.total/10000).plot(figsize=(12,4),grid = True);
df[symbols].mean(axis=1).plot(figsize=(12,4),grid=True);
Выход из строя[499]:
В [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)
В [504]:
e.account['USDT']
Выход[504]:
В [505]:
(res.total/10000).plot(figsize=(12,4),grid = True);
df[symbols].mean(axis=1).plot(figsize=(12,4),grid=True);
Выход[505]:
В целом, 2021 год будет бычьим рынком для поддельных монет и годом снижения для Биткоина. Рыночная стоимость Биткоина упала до 40% сейчас с 70% в начале года, что является самым низким уровнем в истории. Поэтому средняя прибыль от покупки и хранения поддельных товаров в прошлом году намного выше, чем от хранения Биткоина. Ожидая 2022 года, если вы считаете, что на текущем рынке в будущем все еще будет несколько сотен валют, вы можете смело диверсифицировать свои позиции и терпеливо ждать. Если вы особенно оптимистичны по отношению к нескольким валютам или среднему рынку, вы можете использовать вращающуюся стратегию, чтобы получить избыточную прибыль без раздумий. Если вы думаете, что вещи достигнут друг друга, когда они обратятся против себя, вы можете торговаться на биткоин, чтобы получить лучшую прибыль и безопасность.