Last active
June 20, 2017 15:18
-
-
Save darden1/7e700c58cdd8edf1d9137960a609de29 to your computer and use it in GitHub Desktop.
BackTest.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
import poloniex | |
import time | |
import datetime | |
from sklearn import tree | |
import matplotlib.pyplot as plt | |
def main(): | |
# --トレーニング用パラメータ | |
theNumberOfTrainData=29 #トレーニングデータ数 | |
theNumberOfTrainAndKyoushiSet=30 #トレーニングデータと教師データのセット数 | |
studyTrialTimes = 200 #予測のトライアル数(予測結果がばらつくので1回の予測結果を出すために実施する試行回数(取りあえずこのままにしておいてください。) | |
# --バックテストパラメータ | |
plotGraphFlag = 1 # バックテスト結果の資金グラフをプロットしますか?yes:1。no:0 | |
initialFund = 1000 # 初期資金 | |
spread = 0 #取引スプレット(手数料) | |
backTestDays = 30*2 # バックテスト期間(日) | |
dateBTC, dataBTC = getDataPoloniex() | |
dateBTC.reverse() | |
dataBTC.reverse() | |
data = changeData(dataBTC) | |
print('-----------------------------------------') | |
print('バックテストの実施') | |
print('-----------------------------------------') | |
print('※過去のデータから資金上昇率を算出します。上昇シグナル時に現物で買い。下降シグナル時は何もしません。ポジションは1日ごとに決裁します。') | |
seitouritsuUp, seitouritsuDown, increasedFundRatio, increasedBTCPriceRatio, simOutputStr = backTest(data, dateBTC, dataBTC, theNumberOfTrainData,theNumberOfTrainAndKyoushiSet, studyTrialTimes, initialFund, spread, backTestDays, plotGraphFlag) | |
print(simOutputStr) | |
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(figsize=(11, 6)) | |
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