首页 > 比特币 > 正文

数据告诉你,比特币还在周期底部

分类:教程许晓笛小笛 2020-03-23 15:01
 

  上一篇文章准备好数据之后,我们就可以选择合适的算法,并对算法进行训练,并针对目前的数据分析其所处的周期相位。

sklearn 及其分类器算法介绍

  Scikit-learn(sklearn)是机器学习中常用的第三方模块,对常用的机器学习方法进行了封装,包括回归(Regression)、降维(Dimensionality Reduction)、分类(Classfication)、聚类(Clustering)等方法。sklearn 具有简单、高效、严谨的特点,sklearn 只收录经过长时间验证的成熟算法,并且在实现上做到了尽量优化。所以一般的机器学习算法直接调用 sklearn 就可以。

  sklearn 常用的分类器算法有逻辑回归、朴素贝叶斯、K近邻、支持向量机 、决策树、随机森林等,各个算法的分类原理和效果可以直观地通过下面的图片表示:

  数据告诉你,比特币还在周期底部

Python 实现

  在理论的基础上,我们分三个部分实现我们完整的python程序:

  数据获取与标记(1-get-and-label-data.ipynb)

  模型训练与保存(2-train-model.ipynb)

  新数据分析(3-predict.ipynb)

  项目开源地址:
https://github.com/xxd9980/bitcoin-phase-index

python实现:数据获取与标记

  1-get-and-label-data.ipynb

  首先,从 coinmarketcap 网站获取比特币历史数据,并保存在 data_original.csv 文件中:

import time
import requests
import json
import csv# 获取当前时间戳
time_stamp = int(time.time())
print(f"Now timestamp: {time_stamp}")
# 1367107200
# 构造请求路径
request_link = f"https://web-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical?convert=USD&slug=bitcoin&time_end={time_stamp}&time_start=1367107200"
print("Request link: " + request_link)
# 请求 coinmarketcap 接口,获取直到今天的历史数据
r = requests.get(url = request_link)
#print(r.content)
content = json.loads(r.content)
#print(type(content))
quoteList = content['data']['quotes']
#print(quoteList)# 将请求到的数据写入 data_original.csv
# for windows, newline=''
with open('data_original.csv','w' ,encoding='utf8',newline='') as f:
    csv_write = csv.writer(f)
    csv_head = ["Date","Price","Volume"]
    csv_write.writerow(csv_head)    for quote in quoteList:
        quote_date = quote["time_open"][:10]
        quote_price = "{:.2f}".format(quote["quote"]["USD"]["close"])
        quote_volume = "{:.2f}".format(quote["quote"]["USD"]["volume"])
        csv_write.writerow([quote_date, quote_price, quote_volume])print("Done")

  之后将刚才的 data_original.csv 读入到内存中,为什么要先保存,再读回来呢?这样就可以避免每次都请求网络接口获取数据,在数据没有更新时,可以直接运行这个 cell,直接读取数据。

import pandas as pd
import matplotlib.pyplot as pltseries = pd.DataFrame()
# 使用 pandas 读取 data_original.csv 文件
df = pd.read_csv("data_original.csv")
series['Date'] = df['Date'].tolist()
series['Price'] = df['Price'].tolist()
series['Volume'] = df['Volume'].tolist()
print(series)

  之后生成数据标记,所谓标记就是人工标注之前明天的数据是属于哪个相位(阶段),然后将带有标记的数据保存在 data_labeled.csv 文件中。

# 生成数据标记数组,未来有新数据时需要继续标记时,修改此行代码即可
lable = ["Rise"] * 31 + ["Top"] * 369 + ["Decline"] * 370 + ["Bottom"] * 369 + ["Rise"] * 370 + ["Top"] * 369 + ["Decline"] * 370 + ["Bottom"] * 266
# 将标记加入原始数据
Phase = pd.Series(lable, name = 'Phase')
series = series.join(Phase)
# 将原始数据和标记一起存入 data_labeled.csv
series.to_csv("data_labeled.csv", index = 0)

  至此,我们就得到了一份数据文件data_labeled.csv,含有原始数据和相位标记。data_labeled.csv 内容如下:

  数据告诉你,比特币还在周期底部

python实现:模型训练与保存

  2-train-model.ipynb

  首先从 data_labeled.csv

import pandas as pd
import matplotlib.pyplot as pltdf = pd.read_csv("data_labeled.csv")
print(df)

  接下来计算数据的对数、MA、CCI、ROC、BB、Force Index、指标,已经在上一篇文章介绍过,不再赘述。

  处理空数据的地方要修改一下:需要新建一个数组将labels(标记)保持下来,并将数据中本身的标记数据删除,因为如果输入的数据已经携带了最后的结果,那么训练算法就没有任何意义了。

df = df.drop('Date', axis=1)
df = df.drop('SMA1000', axis=1)
df = df.drop('EMA1000', axis=1)
df = df.drop('SMA1000Log', axis=1)
df = df.drop('EMA1000Log', axis=1)
df = df.drop('BBU1000', axis=1)
df = df.drop('BBL1000', axis=1)
df = df.drop('BBU1000Log', axis=1)
df = df.drop('BBL1000Log', axis=1)
df = df.drop(df.index[0:499])
df = df.reset_index(drop=True)
df = df.dropna()
labels = np.array(df["Phase"])
# REMEBER DROP LABEL!
# 不要忘了删除标记
df = df.drop('Phase', axis=1)

  接下来使用 sklearn 中的各种分类器算法进行训练,并且评估各个算法的效果:

from sklearn.model_selection import KFold
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB
from sklearn import svm
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier# 验证函数,用于测试机器学习算法的正确率
def accuracy(test_labels, pred_lables):    
    correct = np.sum(test_labels == pred_lables)   
    n = len(test_labels)    
    return float(correct) / n# 将训练的流程抽取出来
def train_and_predict(clf, kf, data, labels):
    result_set = []
    for train, test in kf.split(data):
        clf.fit(data.iloc[train, :], labels[train])
        result=clf.predict(data.iloc[test])
        result_set.append((result, test))
    score=[]
    for result in result_set:  
        #print (labels[result[1]], result[0])
        a=accuracy(labels[result[1]], result[0])
        score.append(a)
    print("Score: " + clf.__class__.__name__)
    print(score)# 对训练集进行k折抽取,这里将数据随机分为5份,其中4分用来训练,1份用来验证        
kf = KFold(n_splits=5, shuffle=True)
print("------------------------------------------------")
clf = LogisticRegression(solver='liblinear')
train_and_predict(clf, kf, df, labels)
print("------------------------------------------------")
clf = GaussianNB()
train_and_predict(clf, kf, df, labels)
print("------------------------------------------------")
clf = svm.SVC() 
train_and_predict(clf, kf, df, labels)
print("------------------------------------------------")
clf = DecisionTreeClassifier()  
train_and_predict(clf, kf, df, labels)
print("------------------------------------------------")
clf = RandomForestClassifier(n_estimators = 500)
train_and_predict(clf, kf, df, labels)
print("------------------------------------------------")

  得到结果:

--------------------------------------------------------------------------------------------------------
Score: LogisticRegression
[0.43424317617866004, 0.3920595533498759, 0.36724565756823824, 0.3325062034739454, 0.3771712158808933]Score: GaussianNB
[0.48635235732009924, 0.5037220843672456, 0.49627791563275436, 0.5210918114143921, 0.5260545905707196]Score: SVC
[0.31265508684863524, 0.3052109181141439, 0.337468982630273, 0.3225806451612903, 0.2729528535980149]Score: DecisionTreeClassifier
[0.9950372208436724, 0.9975186104218362, 0.9950372208436724, 0.9950372208436724, 0.9950372208436724]Score: RandomForestClassifier
[0.9975186104218362, 1.0, 0.9950372208436724, 0.9900744416873449, 0.9975186104218362]

  可以看到性能最好的是随机森林算法,不过这里非常高的正确率有过拟合的可能性,对于过拟合的优化未来我们有时间再进一步调参处理。

  然后采用随机森林算法,使用全部数据进行训练生成最终版本的分类算法,并将算法保存到 model.m 文件中。

import joblib# 采用随机森林算法
clf = RandomForestClassifier(n_estimators = 500)
# 使用全部数据进行训练
clf.fit(df, labels)
# 将算法保存到 model.m 文件中
joblib.dump(clf, "model.m")

  至此,我们训练好了我们所需的算法。

python实现:新数据分析

  3-predict.ipynb

  这一部分我们对新出现的数据进行分析,具体来说,对于近几天未标记的数据,通过算法判断其所处的相位。

  这部分开始还是从 data_labeled.csv 文件读取数据、计算金融指标、删除不需要的数据,跟第二部分基本相同,关键的是从数据中找到未被标记的数据并通过算法判断其相位(在周期中所处的阶段)。

from sklearn.ensemble import RandomForestClassifier
import joblibclf = RandomForestClassifier()
# 从 model.m 载入模型参数
clf = joblib.load("model.m")print("Predict Data:")
# 遍历模型,寻找未被标记的数据
for index, row in df.iterrows():
    if(pd.isna(row["Phase"])):     
        #print(row)
        #print(index)
        # 分析数据,判断其相位
        phase_predicted = clf.predict(df_data_for_predict.iloc[index,:].values.reshape(1,-1))
        print(df.loc[index,"Date"] + ": " + phase_predicted[0])

  得到结果:

Predict Data:
2020-03-17: Bottom
2020-03-18: Bottom
2020-03-19: Bottom
2020-03-20: Bottom
2020-03-21: Bottom

  至此,我们得到了未被标记数据的分析结果:目前还位于周期底部。

开源地址

  https://github.com/xxd9980/bitcoin-phase-index

系列文章

  如何获取比特币历史数据标记数据与建立训练集

  数据告诉你,比特币还在周期底部

本文标签:数据 比特币 周期底部

上一篇:预测未来十年的比特币

下一篇:比特币的阴谋论你知道多少?

猜您喜欢
关于我们联系我们作者投稿APP下载