Skip to content

Instantly share code, notes, and snippets.

@darden1
Last active December 7, 2016 11:18
Show Gist options
  • Save darden1/15e4924fc12ff4e32f0ec51436a07dd7 to your computer and use it in GitHub Desktop.
Save darden1/15e4924fc12ff4e32f0ec51436a07dd7 to your computer and use it in GitHub Desktop.
BackTestOptimization.py
# -*- coding: utf-8 -*-
import poloniex
import time
import datetime
from sklearn import tree
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import pickle
def main():
# --トレーニング用パラメータ
#トレーニングデータ数
theNumberOfTrainData_Min=20
theNumberOfTrainData_Max = 40
# トレーニングデータと教師データのセット数
theNumberOfTrainAndKyoushiSet_Min=20
theNumberOfTrainAndKyoushiSet_Max = 40
studyTrialTimes = 200 #予測のトライアル数(予測結果がばらつくので1回の予測結果を出すために実施する試行回数(取りあえずこのままにしておいてください。)
# --バックテストパラメータ
plotGraphFlag = 0 # バックテスト結果の資金グラフをプロットしますか?yes:1。no:0 (最適化時実行は0にしてください。)
initialFund = 1000 # 初期資金
spread = 0 # 取引スプレット(手数料)
backTestDays = 30*2 # バックテスト期間(日)
dateBTC, dataBTC = getDataPoloniex()
dateBTC.reverse()
dataBTC.reverse()
data = changeData(dataBTC)
X = np.arange(theNumberOfTrainData_Min,theNumberOfTrainData_Max+1,1)
Y = np.arange(theNumberOfTrainAndKyoushiSet_Min,theNumberOfTrainAndKyoushiSet_Max+1,1)
X, Y = np.meshgrid(X, Y)
Z = np.zeros([len(Y[:]), len(X[0])])
for i in range(0, len(X[0])):
for j in range(0, len(Y[:])):
theNumberOfTrainData=X[j][i]
theNumberOfTrainAndKyoushiSet=Y[j][i]
seitouritsuUp, seitouritsuDown, increasedFundRatio, increasedBTCPriceRatio, simOutputStr = backTest(data, dateBTC, dataBTC, theNumberOfTrainData,theNumberOfTrainAndKyoushiSet, studyTrialTimes, initialFund, spread, backTestDays, plotGraphFlag)
Z[j][i]=increasedFundRatio
print(simOutputStr)
print('---------------------------------------')
maxZRow = np.where(Z == np.max(Z))[0][0]
maxZCol = np.where(Z == np.max(Z))[1][0]
theNumberOfTrainData_Opt=X[maxZRow][maxZCol]
theNumberOfTrainAndKyoushiSet_Opt=Y[maxZRow][maxZCol]
theDateOpt=datetime.datetime.now()
backTestOptResult={"X":X,"Y":Y,"Z":Z,"theNumberOfTrainData_Opt":theNumberOfTrainData_Opt,"theNumberOfTrainAndKyoushiSet_Opt":theNumberOfTrainAndKyoushiSet_Opt,"theDateOpt":theDateOpt}
with open('backTestOptResult.pickle', mode='wb') as f:
pickle.dump(backTestOptResult, f)
print('最適解(資金上昇率): ' + str(round(Z[maxZRow][maxZCol]*100,1)) + '%')
print('最適トレーニングデータ数: ' + str(theNumberOfTrainData_Opt))
print('最適トレーニングデータと教師データのセット数: ' + str(theNumberOfTrainAndKyoushiSet_Opt))
fig = plt.figure()
ax = Axes3D(fig)
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=plt.cm.hot)
ax.contourf(X, Y, Z, zdir='z', offset=-2, cmap=plt.cm.hot)
ax.set_xlabel('theNumberOfTrainData')
ax.set_ylabel('theNumberOfTrainAndKyoushiSet')
ax.set_zlabel('increasedFundRatio')
plt.show()
def backTest(data, dateBTC, dataBTC, theNumberOfTrainData,theNumberOfTrainAndKyoushiSet, studyTrialTimes, initialFund, spread, backTestDays, plotGraphFlag):
realValue = []
predictionValue = []
fund = [initialFund]
pastDay = 0
seitouUp = 0
seitouDown = 0
for trainStartDay in range(backTestDays, 0, -1):
y_Prediction, y = predictionTommorowBTCForBackTest(data, trainStartDay, theNumberOfTrainData, theNumberOfTrainAndKyoushiSet, studyTrialTimes)
realValue.append(y)
predictionValue.append(y_Prediction)
pastDay += 1
if y_Prediction == y:
if y_Prediction == 1:
seitouUp += 1
fund.append(fund[pastDay - 1] * (1 + abs(data[trainStartDay - 1]) - spread))
else:
seitouDown += 1
#---fund.append(fund[pastDay - 1] * (1 + abs(data[trainStartDay - 1]) - spread))
fund.append(fund[pastDay - 1])
else:
if y_Prediction == 1:
fund.append(fund[pastDay - 1] * (1 - abs(data[trainStartDay - 1]) - spread))
else:
#---fund.append(fund[pastDay - 1] * (1 - abs(data[trainStartDay - 1]) - spread))
fund.append(fund[pastDay - 1])
# ----バックテスト結果出力
outputStr = '・トレーニングデータ数: ' + str(theNumberOfTrainData) +'\n'
outputStr += '・トレーニングデータと教師データのセット数: ' + str(theNumberOfTrainAndKyoushiSet)+'\n'
outputStr += '・バックテスト期間: 過去' + str(backTestDays) + '日\n'
seitouritsuUp = float(seitouUp) / sum(predictionValue)
seitouritsuDown = float(seitouDown) / (backTestDays - sum(predictionValue))
outputStr += '・正答率(上昇時): ' + str(round(seitouritsuUp * 100,1)) + '%' + '\n'
outputStr += '・正答率(下降時): ' + str(round(seitouritsuDown * 100,1)) + '%' + '\n'
trainStartDay=0
dataBTCOnBackTest = dataBTC[trainStartDay:trainStartDay+backTestDays+1]
dataBTCOnBackTest.reverse()
increasedFundRatio=(fund[-1]-fund[0])/fund[0]
increasedBTCPriceRatio=(dataBTCOnBackTest[-1]-dataBTCOnBackTest[0])/dataBTCOnBackTest[0]
outputStr += '・資金上昇率: ' + str(round(increasedFundRatio*100,1)) + '% (初期資金は$' +str(fund[0])+'。最終資金は$' +str(fund[-1])+'。)' + '\n'
outputStr += '・BTC価格上昇率: ' + str(round(increasedBTCPriceRatio*100,1)) + '% (初期BTC価格は$' +str(dataBTCOnBackTest[0])+'。最終BTC価格は$' +str(dataBTCOnBackTest[-1])+'。)' + '\n'
# ----資金推移グラフ
if(plotGraphFlag):
# ----Plot Fund
dateBTCOnBackTest = dateBTC[trainStartDay:trainStartDay + backTestDays + 1]
dateBTCOnBackTest.reverse()
fig1, ax1 = plt.subplots()
p1, = ax1.plot(dateBTCOnBackTest, fund, '-ob')
ax1.set_title("Simulation with past data")
ax1.set_xlabel("Day")
ax1.set_ylabel("Fund[$]")
plt.grid(fig1)
# ----Plot BTC Price
ax2 = ax1.twinx()
p2, = ax2.plot(dateBTCOnBackTest, dataBTCOnBackTest, '-or')
ax2.set_ylabel('BTC price[$]')
ax1.legend([p1, p2], ["Fund", "BTC price"], loc="upper left")
plt.show(fig1)
return seitouritsuUp, seitouritsuDown, increasedFundRatio, increasedBTCPriceRatio, outputStr
def getDataPoloniex():
polo = poloniex.Poloniex()
polo.timeout = 2
chartUSDT_BTC = polo.returnChartData('USDT_BTC', period=polo.DAY, start=time.time() - polo.DAY * 500, end=time.time())
tmpDate = [chartUSDT_BTC[i]['date'] for i in range(len(chartUSDT_BTC))]
date = [datetime.datetime.fromtimestamp(tmpDate[i]).date() for i in range(len(tmpDate))]
data = [float(chartUSDT_BTC[i]['open']) for i in range(len(chartUSDT_BTC))]
return date ,data
def changeData(data):
newData=[]
for i in range(0, len(data) - 1):
newData.append(float(data[i] - data[i + 1]) / data[i + 1])
newData.append(0)
return newData
def preparationTrainAndKyoushiSets(data,trainStartDay,theNumberOfTrainData,theNumberOfTrainAndKyoushiSet):
train_X = []
train_y = []
for i in range(0,theNumberOfTrainAndKyoushiSet):
train_X.append(data[trainStartDay+1+i:trainStartDay+theNumberOfTrainData+1+i])
train_y.append([int(0 < data[trainStartDay+i])])
return train_X, train_y
def predictionTommorowBTCForBackTest(data, trainStartDay, theNumberOfTrainData,theNumberOfTrainAndKyoushiSet, studyTrialTimes):
train_X, train_y = preparationTrainAndKyoushiSets(data, trainStartDay, theNumberOfTrainData,theNumberOfTrainAndKyoushiSet)
X=data[trainStartDay:trainStartDay+theNumberOfTrainData]
y = int(0 < data[trainStartDay-1])
y_PredictionTommorow=[]
for i in range(0, theNumberOfTrainAndKyoushiSet):
clf = tree.DecisionTreeClassifier()
clf.fit(train_X, train_y)
y_PredictionTommorow.append(clf.predict([X])[0])
upOrDownRatio = sum(y_PredictionTommorow) * 1.0 / len(y_PredictionTommorow)
return int(upOrDownRatio>0.5),y
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment