3
tập trung vào
1444
Người theo dõi

Đánh giá thị trường tiền điện tử năm 2021 và chiến lược 10x đơn giản nhất mà bạn đã bỏ lỡ

Được tạo ra trong: 2021-12-31 17:13:19, cập nhật trên: 2023-09-15 20:40:22
comments   4
hits   4212

Đánh giá thị trường tiền điện tử năm 2021 và chiến lược 10x đơn giản nhất mà bạn đã bỏ lỡ

2021年就要过去,从DEFI到GAMEFI热点层出不穷,整体大盘仍然是牛市。现在回过头来总结,你2021年收益多少?错过了什么机会?有什么成功的投资?最近我拉取了一下过去一年的历史行情,发现了一个令人意外的简单暴利策略,但就是多币种指数。

交易所上架币种太多了,有很多注定默默无闻,甚至有可能被退出交易。这里我们选择上线过币安永续合约的币种,它们一般经过了考验,是被认可的主流币种,相对安全。经过简单的筛选,去掉一些指数币,最终得到134个币种。

import requests
from datetime import date,datetime
import time
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
## 当前交易对
Info = requests.get('https://fapi.binance.com/fapi/v1/exchangeInfo')
symbols = [s['symbol'] for s in Info.json()['symbols']]
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)
print(len(symbols_f))

过去一年市场

然后我们获取它们过去一年的日线收盘价,注意到一些币的上架时间较短,因此需要填充数据。对数据进行归一化处理,可以算出指数。

最终的指数收益约为12倍,就是说如果2021年1月1日平均买入这134个币,什么都不做的最终收益为12倍,估计90%以上的人都没有跑赢平均指数。其中跌幅最大的币:ICP跌93%, DODO跌85%, LINA跌75%。涨幅接近百倍的有:SOL、FTM、LUNA、MATIC、SAND、AXS。其中AXS涨幅168倍,是最大的黑马。中位数涨幅为3倍,可以说主要是靠公链和游戏把指数拉起来的。为了防止幸存者偏差,把期间永续新上币种排除在外,也取得了接近11倍的收益。是单纯的持有BTC的7倍收益。

这是个令人绝望的收益率,辛辛苦苦费尽心思做各种各样的策略,还没有一年躺平赚的多。但需要注意的是,其中的几个比涨幅实在太过于巨大,明显偏离了指数,如果年初没有选到这些币,收益将会接近中位数,就远远没有那么突出了。

#获取任意周期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 = 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
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
df_all_s.tail() #数据结构
df_all = df_all_s.fillna(method='bfill')#填充数据
df_norm = df_all/df_all.iloc[0] #归一化
df_norm.mean(axis=1).plot(figsize=(12,4),grid=True);
#最终指数收益图
#中位数涨幅
df_norm.median(axis=1).plot(figsize=(12,4),grid=True);
#涨跌排名
print(df_norm.iloc[-1].round(2).sort_values().to_dict())
#当前价格与年内最高点相比最大回撤
print((1-df_norm.iloc[-1]/df_norm.max()).round(2).sort_values().to_dict())
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
#不包含新上币
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);
#相对于比特币
(df.mean(axis=1)/df.BTCUSDT).plot(figsize=(12,4),grid=True);
#还是用原来的回测引擎
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)
#为了回测更加准确,爬取了小时K线
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
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);

平衡策略的表现

回测选择了2021年1月1日上线币安永续合约的所有币种,K线周期为1h,参数为持仓低于平均值的5%开始补仓,超过5%卖出。当回测为全币种时,最终策略收益为7.7倍。明显不如13倍的平均收益。这也实在预料之中,毕竟几个涨幅百倍的币实在太特殊了,平衡策略会把它们全部卖飞。

如果回测选择去掉涨幅最高的10个币,只考察相对平庸的币种,最终收益4.8倍,远超3.4倍的平均表现。

如果只轮动涨幅最高的3个币,最终收益为373倍,远超过了160倍的平均表现。这说明,如果所选轮动币种的趋势和涨幅趋于一致,那么轮动的结果将远好于不轮动的躺平。

#全币种回测
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)
e.account['USDT']
#全币种回测表现
(res.total/10000).plot(figsize=(12,4),grid = True); 
df[symbols].mean(axis=1).plot(figsize=(12,4),grid=True);
#去掉涨幅巨大的币种
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)
e.account['USDT']
(res.total/10000).plot(figsize=(12,4),grid = True); 
df[symbols].mean(axis=1).plot(figsize=(12,4),grid=True);
#只会测涨幅最高的币
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)
e.account['USDT']
(res.total/10000).plot(figsize=(12,4),grid = True); 
df[symbols].mean(axis=1).plot(figsize=(12,4),grid=True);

总结

总的来看,2021年是山寨币的大牛市,比特币落寞的一年。比特币的市值占比一路从年初的70%跌倒现在40%,已经是历史最低水平了,所以过去一年买入山寨并持有获取的平均收益远远高于持有比特币。展望2022年,如果你认为未来仍然有几个百倍币在当前市场上诞生,可以大胆分散持有然后耐心等待。如果你特别看好几个币或者看好平均市场,可以用轮动策略无脑获取超额的收益,如果你认为物极必反,可以抄底比特币,获得更好的收益和安全性。