Les ressources ont été chargées... Je charge...

Examen du marché de la monnaie numérique en 2021 et la stratégie 10 fois plus simple manquée

Auteur:FMZ~Lydia, Créé: 2022-10-26 16:12:49, Mis à jour: 2023-09-15 20:41:17

img

Résumé pour 2021 et stratégies à venir

2021 touche à sa fin, et des points chauds de DEFI à GAMEFI émergent dans un flux sans fin, et le marché global est toujours un marché haussier. Maintenant, regardez en arrière et résumez, combien avez-vous gagné en 2021? Quelles opportunités avez-vous manquées? Quels ont été quelques investissements réussis? Récemment, j'ai jeté un coup d'œil au marché historique de l'année écoulée et j'ai trouvé une stratégie de profit simple et inattendue, qui est un indice multi-monnaies.

Il y a tellement de devises sur l'échange, dont beaucoup sont destinées à être inconnues et peuvent même être retirées du commerce. Ici, nous choisissons la monnaie du contrat perpétuel Binance qui a été utilisée sur le marché. Ils sont généralement testés et reconnus comme des devises traditionnelles, qui sont relativement sûres. Après un simple criblage, certaines devises d'indice ont été retirées et 134 devises ont finalement été obtenues.

Dans [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

Dans [144]:

## Current trading pairs
Info = requests.get('https://fapi.binance.com/fapi/v1/exchangeInfo')
symbols = [s['symbol'] for s in Info.json()['symbols']]

Dans [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)

Dans [155]:

print(len(symbols_f))

Marché au cours de l'année écoulée

Nous obtenons ensuite leurs prix de clôture quotidiens pour l'année écoulée, en notant que certaines devises ont été sur l'étagère pendant une courte période de temps, nous devons donc remplir les données.

Le rendement final de l'indice est d'environ 12 fois, c'est-à-dire que si vous achetez les 134 pièces le 1er janvier 2021 en moyenne, le rendement final de ne rien faire sera de 12 fois. On estime que plus de 90% des traders ne dépassent pas l'indice moyen. Parmi eux, les devises avec la plus forte baisse sont: ICP a chuté de 93%, DODO a chuté de 85% et LINA a chuté de 75%. Alors que SOL, FTM, LUNA, MATIC, SAND et AXS ont augmenté de près de 100 fois. Parmi eux, AXS a augmenté de 168 fois, ce qui en fait le plus grand cheval noir. La médiane a augmenté de 3 fois, ce qui a été principalement motivé par la chaîne publique et les jeux. Afin d'éviter le biais de survie, nous avons exclu la nouvelle monnaie perpétuelle au cours de la période, et nous avons également réalisé près de 11 fois le bénéfice. C'est 7 fois le bénéfice de BTC pour la survie.

Il s'agit d'un taux de rendement désespéré. J'ai travaillé dur pour faire toutes sortes de stratégies, mais il était loin des bénéfices de ne rien faire en un an. Cependant, il convient de noter que certaines des augmentations spécifiques sont trop grandes et il était dévier de l'indice évidemment. Si ces devises ne sont pas sélectionnées au début de l'année, les bénéfices seront proches de la médiane, ce qui est beaucoup moins rentable.

Dans [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

Dans [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

Dans [165]:

df_all_s.tail() #data structure

À l'extérieur [1]:

Dans [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

À l'extérieur [1]:

img

Dans [175]:

#The median increase
df_norm.median(axis=1).plot(figsize=(12,4),grid=True);

À l'extérieur [1]:

img

Dans [168]:

#Ranking for increase/decrease
print(df_norm.iloc[-1].round(2).sort_values().to_dict())

Dans [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())

Dans [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

Dans [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);

À l'extérieur[208]:

img

Dans [212]:

#Compared with Bitcoin
(df.mean(axis=1)/df.BTCUSDT).plot(figsize=(12,4),grid=True);

À l'extérieur [1]:

img

Dans [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)

Dans [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

Dans [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);

À l'extérieur[419]:

img

Performance des stratégies équilibrées

Dans le backtest, toutes les devises du contrat perpétuel Binance en ligne du 1er janvier 2021 ont été sélectionnées. La période de la ligne K était de 1h. Le paramètre a commencé à évoluer dans les positions lorsque la position était inférieure de 5% à la moyenne, et à les vendre lorsque la position était supérieure à 5%. Lorsque le backtest est toutes les devises, le rendement stratégique final est de 7,7 fois. Il n'est évidemment pas aussi bon que le rendement moyen de 13 fois. Cela est également attendu. Après tout, plusieurs devises qui ont augmenté cent fois sont trop spéciales, et la stratégie de balance les vendra toutes.

Si l'on retire du backtest les dix monnaies ayant connu la plus forte hausse, seules les monnaies relativement médiocres seront prises en considération et le revenu final sera de 4,8 fois, ce qui dépasse de loin la performance moyenne de 3,4 fois.

Si seulement les 3 devises avec la plus forte hausse sont rotées, les profits finaux seront 373 fois, ce qui est beaucoup plus que la performance moyenne de 160 fois.

Dans [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)

Dans [495]:

e.account['USDT']

À l'extérieur[495]:

Dans [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);

Extrait[496]:

img

Dans [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)

Dans [501]:

e.account['USDT']

À l'extérieur [1]:

Dans [499]:

(res.total/10000).plot(figsize=(12,4),grid = True); 
df[symbols].mean(axis=1).plot(figsize=(12,4),grid=True);

À l'extérieur [499]:

img

Dans [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)

Dans [504]:

e.account['USDT']

Extrait[504]:

Dans [505]:

(res.total/10000).plot(figsize=(12,4),grid = True); 
df[symbols].mean(axis=1).plot(figsize=(12,4),grid=True);

À l'extérieur[505]:

img

Résumé

En général, 2021 sera un marché haussier pour les pièces contrefaites et une année à la baisse pour Bitcoin. La valeur marchande de Bitcoin est tombée à 40% maintenant, contre 70% au début de l'année, ce qui est le niveau le plus bas de l'histoire. Par conséquent, les bénéfices moyens de l'achat et de la détention de marchandises contrefaites au cours de l'année écoulée sont beaucoup plus élevés que ceux de la détention de Bitcoin.


Relationnée

Plus de