目錄
前言
最近開始關注比特幣,在網絡上看到了一種 基於 FGI 指數的比特幣購買策略。看上去比較有道理,但沒有數據支撐是無法讓我信服的,於是利用歷史數據模擬了使用該種策略從 2018年2月2日到2020年7月5日的交易過程。
FGI 指數
類似於美股的恐慌指數,FGI 指數是衡量加密貨幣市場的恐慌指數。alternative.me 提供了每天的 FGI 指數,據該網站介紹,FGI 指數是一個 0 到 100 之間的整數值,0 表示極度恐慌,100 表示嫉妒貪婪。
該網站提供了相關的 api, 可以方便的獲取需要的信息:
https://api.alternative.me/fng/?limit=0&format=json&date_format=cn
limit = 0 表示獲取所有時間段的信息,format = json 表示數據以 json 格式呈現,data_format = cn 表示時間格式以中文格式呈現。更多的參數信息見 原網站。
將數據複製並保存爲 fgi.json,使用 python 進行一些處理。
import json
import pandas as pd
import numpy as np
filename = 'fgi.json'
with open(filename) as f:
fgi_data = json.load(f)['data'] # 打開 json 文件
fgi_df = pd.DataFrame(fgi_data) # 轉化爲 dataframe 格式
fgi_df['value'] = fgi_df['value'].astype(int) # 將 value 列的屬性變爲整型
# 去掉用不到的列
fgi_df.drop(columns = ['value_classification', 'time_until_update'], inplace = True)
# 將 dataframe 逆序,也就是說變爲從 2018 年 2 月 2 日到 2020 年 7 月 5 日
fgi_df = fgi_df.iloc[::-1]
# 2018 年 2 月 1 日的數據多餘了,去掉
fgi_df = fgi_df.drop(882)
# 逆序後,需要將行號變正常
fgi_df.index = pd.Series([i for i in range(882)])
實際處理過程中發現竟然有三天的 FGI 指數的數據缺失了。
fgi_df[0:72]
將缺失的數據用 np.nan 補全:
df_blank = pd.DataFrame({'value': [np.nan, np.nan, np.nan], 'timestamp': ['2018-04-14', '2018-04-15', '2018-04-16']})
fgi_df_tmp1 = fgi_df[0:71]
fgi_df_tmp2 = fgi_df[71:]
fgi_df = fgi_df_tmp1.append(df_blank, ignore_index = True).append(fgi_df_tmp2, ignore_index = True)
現在的 fgi 數據是這個樣子的:
畫個圖看一下變化情況:
from pyecharts import Line
line = Line('FGI 指數的波動情況')
line.add('FGI 指數', fgi_df['timestamp'], fgi_df['value'], is_label_show = True)
line.render()
FGI 指數的獲取暫時告一段落,下面我們進行比特幣價格的爬取。
比特幣價格爬取
比特幣的數據來自 coinmarketcap ,打開網頁,選擇 Bitcoin, 選擇 Historical Data, 選擇時間區間爲 Feb 02, 2018 到 Jul 06,2020。結果如下:
使用 Crome 瀏覽器的檢查功能進行數據定位:
我們需要的數據就是右邊 <td></td> 引起來的部分。使用 xml 語法進行解析:
import requests
from lxml import etree
import pandas as pd
import numpy as np
res = requests.get(r'https://coinmarketcap.com/currencies/bitcoin/historical-data/?start=20180202&end=20200706')
selector = etree.HTML(res.text)
url_infos = selector.xpath('//td') # 使用 xpath 語法獲取所有標籤爲 td 的節點
del url_infos[6200 : 6214] # 該區間的數據是無效的,去掉
# 將數據進行一行一行的存儲
data = []
line = []
i = 0
for url_info in url_infos:
tmp = url_info.xpath('div/text()')
if (i < 7):
try:
line.append(tmp[0].replace(',','')) # 去掉數字中的逗號
except:
line.append(np.nan)
i = i + 1
else:
data.append(line)
line = []
try:
line.append(tmp[0].replace(',',''))
except:
line.append(np.nan)
i = 1
# 將數據轉化成 DataFrame 格式的
arr = np.array(data)
df = pd.DataFrame(arr)
df.columns = ['date', 'open', 'high', 'low', 'close', 'volume', 'market cap']
df['close'] = df['close'].astype(float)
df = df.iloc[::-1] # 將 df 逆序
df.index = pd.Series([i for i in range(885)])
整理好的數據是這個樣子的:
畫個圖看一下比特幣的走勢:
下面講一下基於 FGI 指數的基本策略。
策略
- 在 fgi 指數處於 0-25 之間時買入一個單位(5000 USD)
- 在 fgi 指數處於 25-45 之間時暫停交易
- 在 fgi 指數處於 45-75 之間時賣出一個單位(5000 USD)
- 在 fgi 指數處於 75-100 之間時賣出兩個單位(10000 USD)
用通俗的話來講,就是巴菲特老爺子說的,別人恐懼(fgi < 25) 我貪婪(買入), 別人貪婪(fgi > 45) 我恐懼(賣出)。
首先先看一下基於這個策略,我們的買入賣出的分佈:
從餅圖中,可以看出,我們買入和賣出的天數相差不大。下面進行實際策略的模擬。
說明:(df 是我們將前兩節得到的兩個 DataFrame 進行合併後的結果)
- 當前投入 now_invest
- 當前比特幣的持有數目 now_bitcoins
- 當前盈利 now_earn = now_value - now_invest
- 手中 bitcoin 的價值,按當天收盤時的價格來計算,now_value = now_bitcoins * df['close']
- 買入和賣出的價格按當前最高和最低價格的平均值來計算 (df['high'] + df['low']) / 2
buy = 5000
sell = 5000
sell_double = 10000
now_invest = 0
now_value = 0
now_earn = 0
now_bitcoins = 0
earn = []
invest = []
date = []
for i in range(885):
now_item = df[i:(i+1)]
now_date = now_item['date'][i]
fgi_index = now_item['fgi_index'][i]
avr = (now_item['high'][i] + now_item['low'][i]) / 2
close = now_item['close'][i]
if (fgi_index <= 25.0):
now_invest += buy
now_bitcoins += buy / avr
now_value = now_bitcoins * close
now_earn = now_value - now_invest
earn.append(now_earn)
invest.append(now_invest)
date.append(now_date)
elif (fgi_index > 45.0 and fgi_index < 75.0):
if (now_bitcoins * avr >= sell):
now_invest -= sell
now_bitcoins -= sell / avr
else:
now_invest -= now_bitcoins * avr
now_bitcoins = 0
now_value = now_bitcoins * close
now_earn = now_value - now_invest
earn.append(now_earn)
invest.append(now_invest)
date.append(now_date)
elif (fgi_index > 75.0):
if (now_bitcoins * avr >= sell_double):
now_invest -= sell_double
now_bitcoins -= sell_double / avr
else:
now_invest -= now_bitcoins * avr
now_bitcoins = 0
now_value = now_bitcoins * close
now_earn = now_value - now_invest
earn.append(now_earn)
invest.append(now_invest)
date.append(now_date)
else:
continue
畫出盈虧曲線:
結果非常 amazing 啊,我們從大約 2019 年 6 月開始,投入開始變爲負,也就是說我們開始只用盈利進行投資了。
但是另外一個值得注意的是,從 2018 年 10 月開始到 2019 年 4 月,我們需要經歷半年的虧損期,而在這之間還需要不斷的投入資金,最高時已經接近 60 w USD。在這之間我們能否堅持自己的信念,能否有穩定的現金流是一個很大的問題。
所以說,沒有萬能的策略,資本的市場本就是反人性的。能擁有自己的投資方式,並幾年如一日的堅持下去,才能獲得最後的成功。也算是理解了很多老股民說的用閒錢投資,別加槓桿的原因了。
後記
本人非專業金融系學生,有很多金融知識的錯誤在所難免,歡迎交流!