3
Suivre
1444
Abonnés

Stratégie d'équilibre perpétuel pour acheter au plus bas d'un marché baissier

Créé le: 2022-06-02 10:00:04, Mis à jour le: 2024-12-02 21:36:36
comments   7
hits   5879

Stratégie d’équilibre perpétuel pour acheter au plus bas d’un marché baissier

Dans le passé, FMZ a officiellement publié une stratégie de grille perpétuelle, qui était très populaire parmi les utilisateurs, et le trading en temps réel de TRX a généré beaucoup de bénéfices au cours de l’année écoulée avec des risques contrôlables. La stratégie du réseau unique durable présente également certains problèmes :

  1. Il est nécessaire de définir des paramètres tels que le prix initial, l’espacement de la grille, la valeur de la grille, les modes long et court, etc. Les paramètres sont assez compliqués, ont un impact plus important sur les rendements et sont difficiles à définir pour les novices.
  2. Le risque de vente à découvert de la stratégie de grille perpétuelle est très élevé, tandis que le risque de vente à long terme est relativement faible. Même si la valeur de la grille est fixée à un niveau très bas, l’impact sur le prix de liquidation de la vente à découvert n’est pas significatif.
  3. La grille de contrats perpétuels peut choisir d’aller uniquement à l’achat pour éviter les risques de vente à découvert, ce qui semble être acceptable pour le moment. Cependant, il existe un problème : le prix actuel dépasse le prix initial, ce qui entraîne une position vide et le prix initial doit être réinitialisé.

J’ai déjà écrit un article sur les principes de la stratégie d’équilibre et sa comparaison avec la stratégie de grille, qui peut encore être référencé maintenant : https://www.fmz.com/digest-topic/5930. La stratégie équilibrée maintient toujours une position sur un ratio ou une valeur fixe. Elle vend une partie de la valeur lorsqu’elle monte et en achète une autre lorsqu’elle baisse. Elle peut être facilement mise en place et exécutée. Même si le prix de la monnaie augmente beaucoup, il n’y a aucun risque de passer à côté. Le problème avec la stratégie d’équilibrage au comptant est que l’utilisation du capital est faible et qu’il n’existe aucun moyen simple d’ajouter un effet de levier. Le contrat perpétuel peut résoudre le problème. Si le capital total est de 1 000, vous pouvez détenir 2 000 en montant fixe, ce qui dépasse le capital initial et améliore le taux d’utilisation des fonds. Il existe également un paramètre permettant d’ajuster le ratio, qui contrôle dans quelle mesure il faut augmenter ou diminuer les positions lorsque le prix augmente ou baisse. Par exemple, s’il est défini sur 0,01, cela signifie qu’il faut réduire les positions une fois lorsque le prix augmente de 1 %. et d’augmenter les positions une fois que le prix baisse de 1 %.

Pour les débutants, la stratégie d’équilibre est fortement recommandée. Elle est facile à utiliser et ne nécessite que de définir un paramètre de ratio de détention ou de valeur de détention, et vous pouvez l’exécuter sans vous soucier de la hausse des prix. Ceux qui ont une certaine expérience peuvent choisir la stratégie de grille, décider des limites supérieures et inférieures des fluctuations et des fonds pour chaque grille, améliorer l’utilisation du capital et rechercher un rendement maximal.

Afin de faciliter le backtesting de davantage de paires de trading, ce document montrera le processus complet de backtesting et les utilisateurs pourront ajuster différents paramètres et paires de trading à des fins de comparaison. (La version est Python3, et un agent est nécessaire pour télécharger le marché. Les utilisateurs peuvent télécharger Anancoda3 eux-mêmes ou l’exécuter via le colab de Google)

import requests
from datetime import date,datetime
import time
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import requests, zipfile, io
%matplotlib inline
## 当前交易对
Info = requests.get('https://fapi.binance.com/fapi/v1/exchangeInfo')
symbols = [s['symbol'] for s in Info.json()['symbols']]
symbols = 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)
['FLMUSDT', 'ICPUSDT', 'CHZUSDT', 'APEUSDT', 'DARUSDT', 'TLMUSDT', 'ETHUSDT', 'STMXUSDT', 'ENJUSDT', 'LINKUSDT', 'OGNUSDT', 'RSRUSDT', 'QTUMUSDT', 'UNIUSDT', 'BNBUSDT', 'XLMUSDT', 'ATOMUSDT', 'LPTUSDT', 'UNFIUSDT', 'DASHUSDT', 'BTCUSDT', 'NEOUSDT', 'AAVEUSDT', 'DUSKUSDT', 'XRPUSDT', 'IOTXUSDT', 'CVCUSDT', 'SANDUSDT', 'XTZUSDT', 'IOTAUSDT', 'BELUSDT', 'MANAUSDT', 'IOSTUSDT', 'IMXUSDT', 'THETAUSDT', 'SCUSDT', 'DOGEUSDT', 'CELOUSDT', 'BNXUSDT', 'SNXUSDT', 'ZRXUSDT', 'HBARUSDT', 'DOTUSDT', 'ANKRUSDT', 'CELRUSDT', 'BAKEUSDT', 'GALUSDT', 'ICXUSDT', 'LRCUSDT', 'AVAXUSDT', 'C98USDT', 'MTLUSDT', 'FTTUSDT', 'MASKUSDT', 'RLCUSDT', 'MATICUSDT', 'COMPUSDT', 'BLZUSDT', 'CRVUSDT', 'ZECUSDT', 'RUNEUSDT', 'LITUSDT', 'ONEUSDT', 'ADAUSDT', 'NKNUSDT', 'LTCUSDT', 'ATAUSDT', 'GALAUSDT', 'BALUSDT', 'ROSEUSDT', 'EOSUSDT', 'YFIUSDT', 'SKLUSDT', 'BANDUSDT', 'ALGOUSDT', 'NEARUSDT', 'AXSUSDT', 'KSMUSDT', 'AUDIOUSDT', 'SRMUSDT', 'HNTUSDT', 'MKRUSDT', 'KLAYUSDT', 'FLOWUSDT', 'STORJUSDT', 'BCHUSDT', 'DYDXUSDT', 'ARUSDT', 'GMTUSDT', 'CHRUSDT', 'API3USDT', 'VETUSDT', 'KAVAUSDT', 'WAVESUSDT', 'EGLDUSDT', 'SFPUSDT', 'RENUSDT', 'SUSHIUSDT', 'SOLUSDT', 'RVNUSDT', 'ONTUSDT', 'BTSUSDT', 'ZILUSDT', 'GTCUSDT', 'ZENUSDT', 'ALICEUSDT', 'ETCUSDT', 'TRXUSDT', 'TOMOUSDT', 'FILUSDT', 'ARPAUSDT', 'CTKUSDT', 'BATUSDT', 'SXPUSDT', '1INCHUSDT', 'HOTUSDT', 'WOOUSDT', 'LINAUSDT', 'REEFUSDT', 'GRTUSDT', 'RAYUSDT', 'COTIUSDT', 'XMRUSDT', 'PEOPLEUSDT', 'OCEANUSDT', 'JASMYUSDT', 'TRBUSDT', 'ANTUSDT', 'XEMUSDT', 'DGBUSDT', 'ENSUSDT', 'OMGUSDT', 'ALPHAUSDT', 'FTMUSDT', 'DENTUSDT', 'KNCUSDT', 'CTSIUSDT', 'SHIBUSDT', 'XECUSDT']
#获取任意周期K线的函数
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 =  min(int(time.mktime(datetime.strptime(end, "%Y-%m-%d").timetuple()))*1000 + 8*60*60*1000,time.time()*1000)
    intervel_map = {'m':60*1000,'h':60*60*1000,'d':24*60*60*1000}
    while start_time < end_time:
        mid_time = start_time+1000*int(period[:-1])*intervel_map[period[-1]]
        url = 'https://'+base+'.binance.com/'+base+'/'+v+'/klines?symbol=%s&interval=%s&startTime=%s&endTime=%s&limit=1000'%(symbol,period,start_time,mid_time)
        #print(url)
        res = requests.get(url)
        res_list = res.json()
        if type(res_list) == list and len(res_list) > 0:
            start_time = res_list[-1][0]+int(period[:-1])*intervel_map[period[-1]]
            Klines += res_list
        if type(res_list) == list and len(res_list) == 0:
            start_time = start_time+1000*int(period[:-1])*intervel_map[period[-1]]
        if mid_time >= end_time:
            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 téléchargeant les cours de clôture de toutes les paires de trading de 2021 à ce jour, nous pouvons observer l’évolution de l’indice global du marché : 2021 à 2022 est sans aucun doute un marché haussier, et l’indice a augmenté de 14 fois à un moment donné. On peut dire que Il y a de l’or partout. La valeur de certaines pièces a augmenté de plusieurs centaines de fois. Cependant, en 2022, un marché baissier a commencé et a duré six mois. L’indice a chuté de 80 % et des dizaines de crypto-monnaies ont reculé de plus de 90 %. Ces hausses et baisses brutales reflètent les énormes risques liés aux stratégies de réseau.

L’indice actuel se situe autour de 3, ce qui représente toujours une augmentation de 200 % par rapport au début de 2021. Compte tenu de l’évolution du marché, il devrait s’agir d’un plancher relatif à l’heure actuelle.

Le prix le plus élevé de la monnaie a augmenté de plus de 10 fois par rapport au début de l’année :

‘MKRUSDT’: 10.294, ‘CRVUSDT’: 10.513, ‘STORJUSDT’: 10.674, ‘SKLUSDT’: 11.009, ‘CVCUSDT’: 11.026, ‘SRMUSDT’: 11.031, ‘QTUMUSDT’: 12.066, ‘ALPHAUSDT’: 12.103, ‘ZENUSDT’: 12.631, ‘VETUSDT’: 13.296, ‘ROSEUSDT’: 13.429, ‘FTTUSDT’: 13.705, ‘IOSTUSDT’: 13.786, ‘COTIUSDT’: 13.958, ‘NEARUSDT’: 14.855, ‘HBARUSDT’: 15.312, ‘RLCUSDT’: 15.432, ‘SCUSDT’: 15.6, ‘GALAUSDT’: 15.722, ‘RUNEUSDT’: 15.795, ‘ADAUSDT’: 16.94, ‘MTLUSDT’: 17.18, ‘BNBUSDT’: 17.899, ‘RVNUSDT’: 18.169, ‘EGLDUSDT’: 18.879, ‘LRCUSDT’: 19.499, ‘ANKRUSDT’: 21.398, ‘ETCUSDT’: 23.51, ‘DUSKUSDT’: 23.55, ‘AUDIOUSDT’: 25.306, ‘OGNUSDT’: 25.524, ‘GMTUSDT’: 28.83, ‘ENJUSDT’: 33.073, ‘STMXUSDT’: 33.18, ‘IOTXUSDT’: 35.866, ‘AVAXUSDT’: 36.946, ‘CHZUSDT’: 37.128, ‘CELRUSDT’: 37.273, ‘HNTUSDT’: 38.779, ‘CTSIUSDT’: 41.108, ‘HOTUSDT’: 46.466, ‘CHRUSDT’: 61.091, ‘MANAUSDT’: 62.143, ‘NKNUSDT’: 70.636, ‘ONEUSDT’: 84.132, ‘DENTUSDT’: 99.973, ‘DOGEUSDT’: 121.447, ‘SOLUSDT’: 140.296, ‘MATICUSDT’: 161.846, ‘FTMUSDT’: 192.507, ‘SANDUSDT’: 203.219, ‘AXSUSDT’: 270.41

Le retracement actuel est supérieur à 80 % du point le plus haut :

ICPUSDT’: 0.022, ‘FILUSDT’: 0.043, ‘BAKEUSDT’: 0.046, ‘TLMUSDT’: 0.05, ‘LITUSDT’: 0.053, ‘LINAUSDT’: 0.054, ‘JASMYUSDT’: 0.056, ‘ALPHAUSDT’: 0.062, ‘RAYUSDT’: 0.062, ‘GRTUSDT’: 0.067, ‘DENTUSDT’: 0.068, ‘RSRUSDT’: 0.068, ‘XEMUSDT’: 0.068, ‘UNFIUSDT’: 0.072, ‘DYDXUSDT’: 0.074, ‘SUSHIUSDT’: 0.074, ‘OGNUSDT’: 0.074, ‘COMPUSDT’: 0.074, ‘NKNUSDT’: 0.078, ‘SKLUSDT’: 0.08, ‘DGBUSDT’: 0.081, ‘RLCUSDT’: 0.085, ‘REEFUSDT’: 0.086, ‘BANDUSDT’: 0.086, ‘HOTUSDT’: 0.092, ‘SRMUSDT’: 0.092, ‘RENUSDT’: 0.092, ‘BTSUSDT’: 0.093, ‘THETAUSDT’: 0.094, ‘FLMUSDT’: 0.094, ‘EOSUSDT’: 0.095, ‘TRBUSDT’: 0.095, ‘SXPUSDT’: 0.095, ‘ATAUSDT’: 0.096, ‘NEOUSDT’: 0.096, ‘FLOWUSDT’: 0.097, ‘YFIUSDT’: 0.101, ‘BALUSDT’: 0.106, ‘MASKUSDT’: 0.106, ‘ONTUSDT’: 0.108, ‘CELRUSDT’: 0.108, ‘AUDIOUSDT’: 0.108, ‘SCUSDT’: 0.11, ‘GALAUSDT’: 0.113, ‘GTCUSDT’: 0.117, ‘CTSIUSDT’: 0.117, ‘STMXUSDT’: 0.118, ‘DARUSDT’: 0.118, ‘ALICEUSDT’: 0.119, ‘SNXUSDT’: 0.124, ‘FTMUSDT’: 0.126, ‘BCHUSDT’: 0.127, ‘SFPUSDT’: 0.127, ‘ROSEUSDT’: 0.128, ‘DOGEUSDT’: 0.128, ‘RVNUSDT’: 0.129, ‘OCEANUSDT’: 0.129, ‘VETUSDT’: 0.13, ‘KSMUSDT’: 0.131, ‘ICXUSDT’: 0.131, ‘UNIUSDT’: 0.131, ‘ONEUSDT’: 0.131, ‘1INCHUSDT’: 0.134, ‘IOTAUSDT’: 0.139, ‘C98USDT’: 0.139, ‘WAVESUSDT’: 0.14, ‘DUSKUSDT’: 0.141, ‘LINKUSDT’: 0.143, ‘DASHUSDT’: 0.143, ‘OMGUSDT’: 0.143, ‘PEOPLEUSDT’: 0.143, ‘AXSUSDT’: 0.15, ‘ENJUSDT’: 0.15, ‘QTUMUSDT’: 0.152, ‘SHIBUSDT’: 0.154, ‘ZENUSDT’: 0.154, ‘BLZUSDT’: 0.154, ‘ANTUSDT’: 0.155, ‘XECUSDT’: 0.155, ‘CHZUSDT’: 0.158, ‘RUNEUSDT’: 0.163, ‘ENSUSDT’: 0.165, ‘LRCUSDT’: 0.167, ‘CHRUSDT’: 0.168, ‘IOTXUSDT’: 0.174, ‘TOMOUSDT’: 0.176, ‘ALGOUSDT’: 0.177, ‘EGLDUSDT’: 0.177, ‘ARUSDT’: 0.178, ‘LTCUSDT’: 0.178, ‘HNTUSDT’: 0.18, ‘LPTUSDT’: 0.181, ‘SOLUSDT’: 0.183, ‘ARPAUSDT’: 0.184, ‘BELUSDT’: 0.184, ‘ETCUSDT’: 0.186, ‘ZRXUSDT’: 0.187, ‘AAVEUSDT’: 0.187, ‘CVCUSDT’: 0.188, ‘STORJUSDT’: 0.189, ‘COTIUSDT’: 0.19, ‘CELOUSDT’: 0.191, ‘SANDUSDT’: 0.191, ‘ADAUSDT’: 0.192, ‘HBARUSDT’: 0.194, ‘DOTUSDT’: 0.195, ‘XLMUSDT’: 0.195

#下载所有交易对的收盘价
start_date = '2021-1-1'
end_date = '2022-05-30'
period = '1d'
df_all = pd.DataFrame(index=pd.date_range(start=start_date, end=end_date, freq=period),columns=symbols)
for i in range(len(symbols)):
    #print(symbols[i])
    symbol = symbols[i]
    df_s = GetKlines(symbol=symbol,start=start_date,end=end_date,period=period,base='api',v='v3')
    df_all[symbol] = df_s[~df_s.index.duplicated(keep='first')].close
#指数变化
df_norm = df_all/df_all.fillna(method='bfill').iloc[0] #归一化
df_norm.mean(axis=1).plot(figsize=(15,6),grid=True);

png

#比年初的最高涨幅
max_up = df_all.max()/df_all.fillna(method='bfill').iloc[0]
print(max_up.map(lambda x:round(x,3)).sort_values().to_dict())
{'JASMYUSDT': 1.0, 'ICPUSDT': 1.0, 'LINAUSDT': 1.0, 'WOOUSDT': 1.0, 'GALUSDT': 1.0, 'PEOPLEUSDT': 1.0, 'XECUSDT': 1.026, 'ENSUSDT': 1.032, 'TLMUSDT': 1.039, 'IMXUSDT': 1.099, 'FLOWUSDT': 1.155, 'ATAUSDT': 1.216, 'DARUSDT': 1.261, 'ALICEUSDT': 1.312, 'BNXUSDT': 1.522, 'API3USDT': 1.732, 'GTCUSDT': 1.833, 'KLAYUSDT': 1.891, 'BAKEUSDT': 1.892, 'DYDXUSDT': 2.062, 'SHIBUSDT': 2.281, 'BTCUSDT': 2.302, 'MASKUSDT': 2.396, 'SFPUSDT': 2.74, 'LPTUSDT': 2.75, 'APEUSDT': 2.783, 'ARUSDT': 2.928, 'CELOUSDT': 2.951, 'ZILUSDT': 2.999, 'LTCUSDT': 3.072, 'SNXUSDT': 3.266, 'XEMUSDT': 3.555, 'XMRUSDT': 3.564, 'YFIUSDT': 3.794, 'BANDUSDT': 3.812, 'RAYUSDT': 3.924, 'REEFUSDT': 4.184, 'ANTUSDT': 4.205, 'XTZUSDT': 4.339, 'CTKUSDT': 4.352, 'LITUSDT': 4.38, 'RSRUSDT': 4.407, 'LINKUSDT': 4.412, 'BCHUSDT': 4.527, 'DASHUSDT': 5.037, 'BALUSDT': 5.172, 'OCEANUSDT': 5.277, 'EOSUSDT': 5.503, 'RENUSDT': 5.538, 'XLMUSDT': 5.563, 'TOMOUSDT': 5.567, 'ZECUSDT': 5.654, 'COMPUSDT': 5.87, 'DGBUSDT': 5.948, 'ALGOUSDT': 5.981, 'ONTUSDT': 5.997, 'BELUSDT': 6.101, 'TRXUSDT': 6.116, 'ZRXUSDT': 6.135, 'GRTUSDT': 6.45, '1INCHUSDT': 6.479, 'DOTUSDT': 6.502, 'ETHUSDT': 6.596, 'KAVAUSDT': 6.687, 'ICXUSDT': 6.74, 'SUSHIUSDT': 6.848, 'AAVEUSDT': 6.931, 'BTSUSDT': 6.961, 'KNCUSDT': 6.966, 'C98USDT': 7.091, 'THETAUSDT': 7.222, 'ATOMUSDT': 7.553, 'OMGUSDT': 7.556, 'SXPUSDT': 7.681, 'UNFIUSDT': 7.696, 'XRPUSDT': 7.726, 'TRBUSDT': 8.241, 'BLZUSDT': 8.434, 'NEOUSDT': 8.491, 'FLMUSDT': 8.506, 'KSMUSDT': 8.571, 'FILUSDT': 8.591, 'IOTAUSDT': 8.616, 'BATUSDT': 8.647, 'ARPAUSDT': 9.055, 'UNIUSDT': 9.104, 'WAVESUSDT': 9.106, 'MKRUSDT': 10.294, 'CRVUSDT': 10.513, 'STORJUSDT': 10.674, 'SKLUSDT': 11.009, 'CVCUSDT': 11.026, 'SRMUSDT': 11.031, 'QTUMUSDT': 12.066, 'ALPHAUSDT': 12.103, 'ZENUSDT': 12.631, 'VETUSDT': 13.296, 'ROSEUSDT': 13.429, 'FTTUSDT': 13.705, 'IOSTUSDT': 13.786, 'COTIUSDT': 13.958, 'NEARUSDT': 14.855, 'HBARUSDT': 15.312, 'RLCUSDT': 15.432, 'SCUSDT': 15.6, 'GALAUSDT': 15.722, 'RUNEUSDT': 15.795, 'ADAUSDT': 16.94, 'MTLUSDT': 17.18, 'BNBUSDT': 17.899, 'RVNUSDT': 18.169, 'EGLDUSDT': 18.879, 'LRCUSDT': 19.499, 'ANKRUSDT': 21.398, 'ETCUSDT': 23.51, 'DUSKUSDT': 23.55, 'AUDIOUSDT': 25.306, 'OGNUSDT': 25.524, 'GMTUSDT': 28.83, 'ENJUSDT': 33.073, 'STMXUSDT': 33.18, 'IOTXUSDT': 35.866, 'AVAXUSDT': 36.946, 'CHZUSDT': 37.128, 'CELRUSDT': 37.273, 'HNTUSDT': 38.779, 'CTSIUSDT': 41.108, 'HOTUSDT': 46.466, 'CHRUSDT': 61.091, 'MANAUSDT': 62.143, 'NKNUSDT': 70.636, 'ONEUSDT': 84.132, 'DENTUSDT': 99.973, 'DOGEUSDT': 121.447, 'SOLUSDT': 140.296, 'MATICUSDT': 161.846, 'FTMUSDT': 192.507, 'SANDUSDT': 203.219, 'AXSUSDT': 270.41}
#当前最大回测
draw_down = df_all.iloc[-1]/df_all.max()
print(draw_down.map(lambda x:round(x,3)).sort_values().to_dict())
{'ICPUSDT': 0.022, 'FILUSDT': 0.043, 'BAKEUSDT': 0.046, 'TLMUSDT': 0.05, 'LITUSDT': 0.053, 'LINAUSDT': 0.054, 'JASMYUSDT': 0.056, 'ALPHAUSDT': 0.062, 'RAYUSDT': 0.062, 'GRTUSDT': 0.067, 'DENTUSDT': 0.068, 'RSRUSDT': 0.068, 'XEMUSDT': 0.068, 'UNFIUSDT': 0.072, 'DYDXUSDT': 0.074, 'SUSHIUSDT': 0.074, 'OGNUSDT': 0.074, 'COMPUSDT': 0.074, 'NKNUSDT': 0.078, 'SKLUSDT': 0.08, 'DGBUSDT': 0.081, 'RLCUSDT': 0.085, 'REEFUSDT': 0.086, 'BANDUSDT': 0.086, 'HOTUSDT': 0.092, 'SRMUSDT': 0.092, 'RENUSDT': 0.092, 'BTSUSDT': 0.093, 'THETAUSDT': 0.094, 'FLMUSDT': 0.094, 'EOSUSDT': 0.095, 'TRBUSDT': 0.095, 'SXPUSDT': 0.095, 'ATAUSDT': 0.096, 'NEOUSDT': 0.096, 'FLOWUSDT': 0.097, 'YFIUSDT': 0.101, 'BALUSDT': 0.106, 'MASKUSDT': 0.106, 'ONTUSDT': 0.108, 'CELRUSDT': 0.108, 'AUDIOUSDT': 0.108, 'SCUSDT': 0.11, 'GALAUSDT': 0.113, 'GTCUSDT': 0.117, 'CTSIUSDT': 0.117, 'STMXUSDT': 0.118, 'DARUSDT': 0.118, 'ALICEUSDT': 0.119, 'SNXUSDT': 0.124, 'FTMUSDT': 0.126, 'BCHUSDT': 0.127, 'SFPUSDT': 0.127, 'ROSEUSDT': 0.128, 'DOGEUSDT': 0.128, 'RVNUSDT': 0.129, 'OCEANUSDT': 0.129, 'VETUSDT': 0.13, 'KSMUSDT': 0.131, 'ICXUSDT': 0.131, 'UNIUSDT': 0.131, 'ONEUSDT': 0.131, '1INCHUSDT': 0.134, 'IOTAUSDT': 0.139, 'C98USDT': 0.139, 'WAVESUSDT': 0.14, 'DUSKUSDT': 0.141, 'LINKUSDT': 0.143, 'DASHUSDT': 0.143, 'OMGUSDT': 0.143, 'PEOPLEUSDT': 0.143, 'AXSUSDT': 0.15, 'ENJUSDT': 0.15, 'QTUMUSDT': 0.152, 'SHIBUSDT': 0.154, 'ZENUSDT': 0.154, 'BLZUSDT': 0.154, 'ANTUSDT': 0.155, 'XECUSDT': 0.155, 'CHZUSDT': 0.158, 'RUNEUSDT': 0.163, 'ENSUSDT': 0.165, 'LRCUSDT': 0.167, 'CHRUSDT': 0.168, 'IOTXUSDT': 0.174, 'TOMOUSDT': 0.176, 'ALGOUSDT': 0.177, 'EGLDUSDT': 0.177, 'ARUSDT': 0.178, 'LTCUSDT': 0.178, 'HNTUSDT': 0.18, 'LPTUSDT': 0.181, 'SOLUSDT': 0.183, 'ARPAUSDT': 0.184, 'BELUSDT': 0.184, 'ETCUSDT': 0.186, 'ZRXUSDT': 0.187, 'AAVEUSDT': 0.187, 'CVCUSDT': 0.188, 'STORJUSDT': 0.189, 'COTIUSDT': 0.19, 'CELOUSDT': 0.191, 'SANDUSDT': 0.191, 'ADAUSDT': 0.192, 'HBARUSDT': 0.194, 'DOTUSDT': 0.195, 'XLMUSDT': 0.195, 'AVAXUSDT': 0.206, 'ANKRUSDT': 0.207, 'MTLUSDT': 0.208, 'MANAUSDT': 0.209, 'CRVUSDT': 0.213, 'API3USDT': 0.221, 'IOSTUSDT': 0.227, 'XRPUSDT': 0.228, 'BATUSDT': 0.228, 'MKRUSDT': 0.229, 'MATICUSDT': 0.229, 'CTKUSDT': 0.233, 'ZILUSDT': 0.233, 'WOOUSDT': 0.234, 'ATOMUSDT': 0.237, 'KLAYUSDT': 0.239, 'XTZUSDT': 0.245, 'IMXUSDT': 0.278, 'NEARUSDT': 0.285, 'GALUSDT': 0.299, 'APEUSDT': 0.305, 'ZECUSDT': 0.309, 'KAVAUSDT': 0.31, 'GMTUSDT': 0.327, 'FTTUSDT': 0.366, 'KNCUSDT': 0.401, 'ETHUSDT': 0.416, 'XMRUSDT': 0.422, 'BTCUSDT': 0.47, 'BNBUSDT': 0.476, 'TRXUSDT': 0.507, 'BNXUSDT': 0.64}

Tout d’abord, nous utilisons le code le plus simple pour simuler une tendance à la baisse et voir les prix de liquidation de différentes valeurs de position. Étant donné que la stratégie maintient toujours des positions longues, il n’y a aucun risque de hausse. Le capital initial est de 1 000, le prix de la devise est de 1 et le taux d’ajustement est de 0,01. Les résultats sont les suivants. On peut constater que le risque de liquidation des positions longues n’est pas faible. Avec un effet de levier de 1,5 fois, il peut résister à une baisse de 50 %. Compte tenu de la situation actuelle, il s’agit d’un risque acceptable.

Valeur de position Prix ​​de liquidation long
300 0.035
500 0.133
800 0.285
1000 0.362
1500 0.51
2000 0.599
3000 0.711
5000 0.81
10000 0.904
for Hold_value in [300,500,800,1000,1500,2000,3000,5000,10000]:
    amount = Hold_value/1
    hold_price = 1
    margin = 1000
    Pct = 0.01
    i = 0
    while margin > 0:
        i += 1
        if i>500:
            break
        buy_price = (1-Pct)*Hold_value/amount
        buy_amount = Hold_value*Pct/buy_price
        hold_price = (amount * hold_price + buy_amount * buy_price) / (buy_amount + amount)
        amount += buy_amount
        margin = 1000 + amount * (buy_price - hold_price)
    print(Hold_value, round(buy_price,3))
300 0.035
500 0.133
800 0.285
1000 0.362
1500 0.51
2000 0.599
3000 0.711
5000 0.81
10000 0.904
#还是用原来的回测引擎
class Exchange:
    
    def __init__(self, trade_symbols, fee=0.0004, initial_balance=10000):
        self.initial_balance = initial_balance #初始的资产
        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 #扣除手续费
        self.account['USDT']['fee'] += price*amount*self.fee
        self.account[symbol]['fee'] += price*amount*self.fee

        if cover_amount > 0: #先平仓
            self.account['USDT']['realised_profit'] += -direction*(price - self.account[symbol]['hold_price'])*cover_amount  #利润
            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): #对资产进行更新
        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)

Tout d’abord, nous testons rétrospectivement les performances de la stratégie d’équilibrage TRX. Le drawdown maximum de TRX dans cette phase de marché baissier est relativement faible, il présente donc certaines caractéristiques particulières. Les données sélectionnées sont la ligne K de 5 minutes de 2021 à ce jour, avec un capital initial de 1 000, un ratio d’ajustement de 0,01, une valeur de détention de 2 000 et des frais de traitement de 0,0002.

Le prix initial du TRX était de 0,02676 U, et le prix le plus élevé au cours de la période a atteint 0,18 U. Il se situe actuellement autour de 0,08 U, avec des fluctuations très violentes. Si vous exécutez la stratégie de grille long-short dès le début, vous vous retrouverez inévitablement avec une liquidation de position courte. Une stratégie équilibrée n’est pas un gros problème.

Le rendement final du backtest est de 4524U, ce qui est très proche du rendement de TRX à 0,18. L’effet de levier est inférieur à 2 fois au début et inférieur à 0,4 à la fin. La possibilité de liquidation est de plus en plus faible. Pendant cette période, la valeur des avoirs peut être augmentée. Chance. Mais les revenus inférieurs à 2000U restent inchangés. C’est aussi l’un des inconvénients de la stratégie équilibrée.

symbol = 'TRXUSDT'
df_trx = GetKlines(symbol=symbol,start='2021-1-1',end='2022-5-30',period='5m')
df_trx.close.plot(figsize=(15,6),grid=True);

png

#TRX平衡策略回测
hold_value = 2000
pct = 0.01
e = Exchange([symbol], fee=0.0002, initial_balance=1000)
init_price =  df_trx.iloc[0].open
res_list = [] #用于储存中间结果
e.Buy(symbol,init_price,hold_value/init_price)
e.Update({symbol:init_price})
for row in df_trx.itertuples():
    buy_price = (1-pct)*hold_value/e.account[symbol]['amount']
    sell_price = (1+pct)*hold_value/e.account[symbol]['amount']
    
    while row.low < buy_price:
        e.Buy(symbol,buy_price,pct*hold_value/buy_price)
        e.Update({symbol:row.close})
        buy_price = (1-pct)*hold_value/e.account[symbol]['amount']
        sell_price = (1+pct)*hold_value/e.account[symbol]['amount']
    while row.high > sell_price:
        e.Sell(symbol,sell_price,pct*hold_value/sell_price)
        e.Update({symbol:row.close})
        buy_price = (1-pct)*hold_value/e.account[symbol]['amount']
        sell_price = (1+pct)*hold_value/e.account[symbol]['amount']
    if int(row.time)%(60*60*1000) == 0:
        e.Update({symbol:row.close})
        res_list.append([row.time, row.close, e.account[symbol]['amount'],e.account[symbol]['amount']*row.close, e.account['USDT']['total']-e.initial_balance])
res_trx = pd.DataFrame(data=res_list, columns=['time','price','amount','value','profit'])
res_trx.index = pd.to_datetime(res_trx.time,unit='ms')
print(pct,e.account['USDT']['realised_profit']+e.account['USDT']['unrealised_profit'] ,round(e.account['USDT']['fee'],0))
0.01 4524.226998288555 91.0
#收益
res_trx.profit.plot(figsize=(15,6),grid=True);

png

#实际占用杠杆
(res_trx.value/(res_trx.profit+1000)).plot(figsize=(15,6),grid=True);

png

Testons à nouveau WAVES. Cette cryptomonnaie est assez spéciale. Elle est passée de 6U au début à un sommet de 60U, pour finalement retomber au niveau actuel de 8U. Le bénéfice final est de 4945, ce qui est bien supérieur au bénéfice réalisé en détenant les pièces.

symbol = 'WAVESUSDT'
df_waves = GetKlines(symbol=symbol,start='2021-1-1',end='2022-5-30',period='5m')
df_waves.close.plot(figsize=(15,6),grid=True);

png

#TWAVES平衡策略回测
hold_value = 2000
pct = 0.01
e = Exchange([symbol], fee=0.0002, initial_balance=1000)
init_price =  df_waves.iloc[0].open
res_list = [] #用于储存中间结果
e.Buy(symbol,init_price,hold_value/init_price)
e.Update({symbol:init_price})
for row in df_waves.itertuples():
    buy_price = (1-pct)*hold_value/e.account[symbol]['amount']
    sell_price = (1+pct)*hold_value/e.account[symbol]['amount']
    
    while row.low < buy_price:
        e.Buy(symbol,buy_price,pct*hold_value/buy_price)
        e.Update({symbol:row.close})
        buy_price = (1-pct)*hold_value/e.account[symbol]['amount']
        sell_price = (1+pct)*hold_value/e.account[symbol]['amount']
    while row.high > sell_price:
        e.Sell(symbol,sell_price,pct*hold_value/sell_price)
        e.Update({symbol:row.close})
        buy_price = (1-pct)*hold_value/e.account[symbol]['amount']
        sell_price = (1+pct)*hold_value/e.account[symbol]['amount']
    if int(row.time)%(60*60*1000) == 0:
        e.Update({symbol:row.close})
        res_list.append([row.time, row.close, e.account[symbol]['amount'],e.account[symbol]['amount']*row.close, e.account['USDT']['total']-e.initial_balance])
res_waves = pd.DataFrame(data=res_list, columns=['time','price','amount','value','profit'])
res_waves.index = pd.to_datetime(res_waves.time,unit='ms')
print(pct,e.account['USDT']['realised_profit']+e.account['USDT']['unrealised_profit'] ,round(e.account['USDT']['fee'],0))
0.01 4945.149323437233 178.0
df_waves.profit.plot(figsize=(15,6),grid=True);

png

Au fait, testons à nouveau les performances de la stratégie de grille. L’espacement de la grille est de 0,01 et la valeur de la grille est de 10. Avec une augmentation de près de 10 fois, WAVES et TRX ont tous deux connu d’énormes reculs, WAVES reculant de 5 000 U et TRX de plus de 3 000 U. Si le capital initial est faible, la position sera essentiellement liquidée.

#网格策略
pct = 0.01
value = 10*pct/0.01
e = Exchange([symbol], fee=0.0002, initial_balance=1000)
init_price =  df_waves.iloc[0].open
res_list = [] #用于储存中间结果
for row in df_waves.itertuples():
    buy_price = (value / pct - value) / (value / (pct * init_price) + e.account[symbol]['amount']) 
    sell_price = (value / pct + value) / (value / (pct *init_price) + e.account[symbol]['amount'])

    while row.low < buy_price:
        e.Buy(symbol,buy_price,value/buy_price)
        e.Update({symbol:row.close})
        buy_price = (value / pct - value) / (value / (pct * init_price) + e.account[symbol]['amount']) #买单价格,由于是挂单成交,也是最终的撮合价格=
    while row.high > sell_price:
        e.Sell(symbol,sell_price,value/sell_price)
        e.Update({symbol:row.close})
        sell_price = (value / pct + value) / (value / (pct *init_price) + e.account[symbol]['amount'])
    if int(row.time)%(60*60*1000) == 0:
        e.Update({symbol:row.close})
        res_list.append([row.time, row.close, e.account[symbol]['amount'],e.account[symbol]['amount']*row.close, e.account['USDT']['total']-e.initial_balance])
res_waves_net = pd.DataFrame(data=res_list, columns=['time','price','amount','value','profit'])
res_waves_net.index = pd.to_datetime(res_waves_net.time,unit='ms')
print(pct,e.account['USDT']['realised_profit']+e.account['USDT']['unrealised_profit'] ,round(e.account['USDT']['fee'],0))
0.01 1678.0516101975015 70.0
res_waves_net.profit.plot(figsize=(15,6),grid=True);

png

#网格策略
pct = 0.01
value = 10*pct/0.01
e = Exchange([symbol], fee=0.0002, initial_balance=1000)
init_price =  df_trx.iloc[0].open
res_list = [] #用于储存中间结果
for row in df_trx.itertuples():
    buy_price = (value / pct - value) / (value / (pct * init_price) + e.account[symbol]['amount']) 
    sell_price = (value / pct + value) / (value / (pct *init_price) + e.account[symbol]['amount'])

    while row.low < buy_price:
        e.Buy(symbol,buy_price,value/buy_price)
        e.Update({symbol:row.close})
        buy_price = (value / pct - value) / (value / (pct * init_price) + e.account[symbol]['amount']) 
    while row.high > sell_price:
        e.Sell(symbol,sell_price,value/sell_price)
        e.Update({symbol:row.close})
        sell_price = (value / pct + value) / (value / (pct *init_price) + e.account[symbol]['amount'])
    if int(row.time)%(60*60*1000) == 0:
        e.Update({symbol:row.close})
        res_list.append([row.time, row.close, e.account[symbol]['amount'],e.account[symbol]['amount']*row.close, e.account['USDT']['total']-e.initial_balance])
res_trx_net = pd.DataFrame(data=res_list, columns=['time','price','amount','value','profit'])
res_trx_net.index = pd.to_datetime(res_trx_net.time,unit='ms')
print(pct,e.account['USDT']['realised_profit']+e.account['USDT']['unrealised_profit'] ,round(e.account['USDT']['fee'],0))
0.01 -161.06952570521656 37.0
res_trx_net.profit.plot(figsize=(15,6),grid=True);

png

Résumer

Cette analyse de backtest a utilisé une ligne K de 5 minutes et les fluctuations au milieu n’ont pas été entièrement simulées, de sorte que le rendement réel devrait être légèrement supérieur. En général, la stratégie équilibrée comporte des risques relativement faibles, n’a pas peur de monter en flèche, ne nécessite pas de réglage des paramètres, est relativement pratique à utiliser et convient aux utilisateurs novices. La stratégie de grille est très sensible à la fixation du prix initial et nécessite une certaine appréciation des conditions de marché. À long terme, le risque de vente à découvert est très élevé. Cette vague de marché baissier est restée stable au plus bas pendant un certain temps. De nombreuses pièces ont chuté de plus de 90 % par rapport à leurs sommets. Si vous êtes optimiste à propos de certaines pièces, c’est le bon moment pour entrer sur le marché. Vous souhaiterez peut-être Commencez une stratégie équilibrée pour acheter au plus bas. Ajoutez un peu d’effet de levier pour profiter de la volatilité et des hausses de prix. Cette guerre des mille groupes Binance offrira une utilisation gratuite de la stratégie d’équilibre perpétuel, et tout le monde est invité à en faire l’expérience.