Created
August 28, 2016 18:18
-
-
Save akkijp/9ff3bfcc2b9b724a5aed0766e729cc63 to your computer and use it in GitHub Desktop.
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 numpy as np | |
import pandas as pd | |
from sklearn import tree | |
from sklearn.svm import SVC | |
import matplotlib.pyplot as plt | |
import datetime | |
#--メール送信用 | |
import os.path | |
import smtplib | |
from email import Encoders | |
from email.Utils import formatdate | |
from email.MIMEBase import MIMEBase | |
from email.MIMEMultipart import MIMEMultipart | |
from email.MIMEText import MIMEText | |
def sendMail(l_subject,l_body,l_yourGmailAddress,l_yourGmailAddressPassword): | |
#---Parameters | |
l_SMTP = "smtp.gmail.com" | |
l_PORT = 587 | |
l_from_addr=l_yourGmailAddress | |
l_to_addr = l_yourGmailAddress | |
#---Create message | |
l_msg = MIMEMultipart() | |
l_msg["From"] = l_from_addr | |
l_msg["To"] = l_to_addr | |
l_msg["Date"] = formatdate() | |
l_msg["Subject"] = l_subject | |
l_body = MIMEText(l_body) | |
l_msg.attach(l_body) | |
#---Send mail | |
l_smtpobj = smtplib.SMTP(l_SMTP, l_PORT) | |
l_smtpobj.ehlo() | |
l_smtpobj.starttls() | |
l_smtpobj.login(l_yourGmailAddress, l_yourGmailAddressPassword) | |
l_smtpobj.sendmail(l_from_addr, l_to_addr, l_msg.as_string()) | |
l_smtpobj.close() | |
def importData(l_csvfile): | |
l_rawData = pd.read_csv(l_csvfile) | |
l_date = np.array(l_rawData['Date']) | |
l_data = np.array(l_rawData['Close']) | |
nanIndex = np.where(np.isnan(l_data))[0].tolist() #---find 'nan' | |
l_date = np.delete(l_date, nanIndex) # ---Remove 'nan' | |
l_data = np.delete(l_data, nanIndex) # ---Remove 'nan' | |
return np.array(l_date[::-1]) ,np.array(l_data[::-1]) | |
def changeData(l_data): | |
l_newData=[] | |
for i in range(0, len(l_data) - 1): | |
l_newData.append((l_data[i] - l_data[i + 1]) / l_data[i + 1]) | |
l_newData.append(0) | |
return np.array(l_newData) | |
def trainData(l_data,l_trainStartDay,l_trainDataLength,l_kyoushiDataNumber): | |
l_train_X = [] | |
l_train_y = [] | |
for i in range(0,l_kyoushiDataNumber): | |
l_values=l_data[l_trainStartDay+1+i:l_trainStartDay+l_trainDataLength+1+i] | |
l_train_y.append(int(0 < l_data[l_trainStartDay+i])) | |
l_train_X.append(l_values) | |
return np.array(l_train_X), np.array(l_train_y) | |
def prediction(l_data, l_trainStartDay, l_trainDataLength, l_kyoushiDataNumber, l_predictionTrialTimes): | |
l_train_X, l_train_y = trainData(l_data, l_trainStartDay, l_trainDataLength, l_kyoushiDataNumber) | |
l_X=l_data[l_trainStartDay:l_trainStartDay+l_trainDataLength] | |
l_y = int(0 0.5),l_y | |
def predictionTommorow(l_data, l_trainDataLength, l_kyoushiDataNumber, l_predictionTrialTimes): | |
l_trainStartDay=0 | |
l_train_X, l_train_y = trainData(l_data, l_trainStartDay, l_trainDataLength, l_kyoushiDataNumber) | |
l_X=l_data[l_trainStartDay:l_trainStartDay+l_trainDataLength] | |
l_y_PredictionTommorow=[] | |
for i in range(0, l_predictionTrialTimes): | |
l_clf = tree.DecisionTreeClassifier() | |
l_clf.fit(l_train_X, l_train_y) | |
l_y_PredictionTommorow.append(l_clf.predict(l_X.reshape(1, -1))[0]) | |
l_upOrDownRatio = sum(l_y_PredictionTommorow) * 1.0 / len(l_y_PredictionTommorow) | |
return l_upOrDownRatio | |
def backTest(l_data, l_btcPriceData, l_trainStartDay, l_trainDataLength, l_kyoushiDataNumber, l_predictionTrialTimes, l_initialFund, l_spread, l_trialDays, l_plotGraphFlag): | |
l_realValue = [] | |
l_predictionValue = [] | |
l_fund = [l_initialFund] | |
l_pastDay = 0 | |
l_seitouUp = 0 | |
l_seitouDown = 0 | |
for l_trainStartDay in range(l_trialDays, 0, -1): | |
y_Prediction, y = prediction(l_data, l_trainStartDay, l_trainDataLength, l_kyoushiDataNumber, l_predictionTrialTimes) | |
l_realValue.append(y) | |
l_predictionValue.append(y_Prediction) | |
l_pastDay += 1 | |
if y_Prediction == y: | |
if y_Prediction == 1: | |
l_seitouUp += 1 | |
l_fund.append(l_fund[l_pastDay - 1] * (1 + abs(l_data[l_trainStartDay - 1]) - l_spread)) | |
else: | |
l_seitouDown += 1 | |
#--l_fund.append(l_fund[l_pastDay - 1] * (1 + abs(l_data[l_trainStartDay - 1]) - l_spread)) | |
l_fund.append(l_fund[l_pastDay - 1]) | |
else: | |
if y_Prediction == 1: | |
l_fund.append(l_fund[l_pastDay - 1] * (1 - abs(l_data[l_trainStartDay - 1]) - l_spread)) | |
else: | |
#---fund.append(fund[pastDay - 1] * (1 - abs(l_data[l_trainStartDay - 1]) - l_spread)) | |
l_fund.append(l_fund[l_pastDay - 1]) | |
l_outputStr = '・トレーニングデータ数: ' + str(l_trainDataLength) +'\n' | |
l_outputStr += '・教師データ数: ' + str(l_kyoushiDataNumber)+'\n' | |
l_outputStr += '・バックテスト期間: 過去' + str(l_trialDays) + '日\n' | |
l_seitouritsuUp = float(l_seitouUp) / sum(l_predictionValue) | |
l_seitouritsuDown = float(l_seitouDown) / (l_trialDays - sum(l_predictionValue)) | |
# ----Print simulation result | |
l_outputStr += '・正答率(上昇時): ' + str(round(l_seitouritsuUp * 100,1)) + '%' + '\n' | |
l_outputStr += '・正答率(下降時): ' + str(round(l_seitouritsuDown * 100,1)) + '%' + '\n' | |
l_btcPrice = l_btcPriceData[l_trainStartDay-1:l_trainStartDay-1+l_trialDays+1] | |
l_btcPrice = l_btcPrice[::-1] | |
l_increasedFundRatio=(l_fund[-1]-l_fund[0])/l_fund[0] | |
l_increasedBTCPriceRatio=(l_btcPrice[-1]-l_btcPrice[0])/l_btcPrice[0] | |
l_outputStr += '・資金上昇率: ' + str(round(l_increasedFundRatio*100,1)) + '% (初期資金は$' +str(l_fund[0])+'。最終資金は$' +str(l_fund[-1])+'。)' + '\n' | |
l_outputStr += '・BTC価格上昇率: ' + str(round(l_increasedBTCPriceRatio*100,1)) + '% (初期BTC価格は$' +str(l_btcPrice[0])+'。最終BTC価格は$' +str(l_btcPrice[-1])+'。)' + '\n' | |
if(l_plotGraphFlag): | |
# ----Plot Fund | |
day1 = range(0, l_trialDays + 1) | |
fig1, ax1 = plt.subplots() | |
p1, = ax1.plot(day1, l_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(day1, l_btcPrice, '-or') | |
ax2.set_ylabel('BTC price[$]') | |
ax1.legend([p1, p2], ["Fund", "BTC price"], loc="upper left") | |
plt.show(fig1) | |
plt.close(1) | |
return l_seitouritsuUp,l_seitouritsuDown,l_increasedFundRatio,l_increasedBTCPriceRatio,l_outputStr | |
if __name__ == "__main__": | |
# --トレーニング用パラメータ | |
trainDataLength=28 #トレーニングデータ数 | |
kyoushiDataNumber=26 #教師データ数 | |
predictionTrialTimes = 200 #予測のトライアル数(予測結果がばらつくので1回の予測結果を出すために実施する試行回数(取りあえずこのままにしておいてください。) | |
#--バックテストパラメータ | |
plotGraphFlag=0 #バックテスト結果の資金グラフをプロットしますか?yes:1。no:0 (スケジューラで自動実行させる時は0にしてください。) | |
initialFund=100000 #初期資金 | |
spread=0 #---0.006 #取引スプレット(手数料) | |
trialDays=30*2 #バックテスト期間(日) | |
#--メール送信パラメータ | |
sendMailFlag=1 #明日のBTC価格の予想結果をメール送信しますか? yes:1。no:0 | |
yourGmailAddress = "**********@gmail.com" #---送信時のメールアドレス(自分のGメールアドレス。自分自身に送信します。) | |
yourGmailAddressPassword = "**********" #---Gメールのログインパスワード | |
outputStr = '-----------------------------------------' + '\n' | |
outputStr += 'BTC価格データダウンロード' + '\n' | |
outputStr += '-----------------------------------------' + '\n' | |
#--- 日本時間の 09:10 a.m.過ぎにCoindeskのデータが更新されるので、その辺りで実行してください。 | |
todayStr = str(datetime.datetime.today())[0:10] | |
tommorrowStr = str(datetime.datetime.today() + datetime.timedelta(1))[0:10] | |
csvfile = 'http://api.coindesk.com/v1/bpi/historical/close.csv?start=2010-07-18&end=' + todayStr + '&index=USD' | |
outputStr += '今日は' +todayStr +'です。\n' | |
outputStr += 'Coindesk(http://www.coindesk.com/price/)からBTC価格データをダウンロードします。' + '\n' | |
outputStr += '(URL: ' + csvfile + ')\n' | |
dateData, btcPriceData = importData(csvfile) | |
data = changeData(btcPriceData) | |
outputStr += '取得データファイル中にある最後の日付は' + dateData[0] + 'でその時のBTCクローズ価格は$' + str(btcPriceData[0]) + 'です。\n' | |
outputStr += '-----------------------------------------' + '\n' | |
outputStr += 'バックテストの実施' + '\n' | |
outputStr += '-----------------------------------------' + '\n' | |
outputStr += '※過去のデータから資金上昇率を算出します。上昇シグナル時に現物で買い。下降シグナル時は何もしません。ポジションは1日ごとに決裁します。' + '\n' | |
trainStartDay=1 | |
seitouritsuUp, seitouritsuDown,increasedFundRatio,increasedBTCPriceRatio, simOutputStr=backTest(data, btcPriceData, trainStartDay, trainDataLength, kyoushiDataNumber, predictionTrialTimes, initialFund, spread, trialDays, plotGraphFlag) | |
outputStr +=simOutputStr | |
outputStr += '-----------------------------------------' + '\n' | |
outputStr += '明日のBTC価格予想' + '\n' | |
outputStr += '-----------------------------------------' + '\n' | |
outputStr += '※' + dateData[0] + 'までのデータから' + todayStr + 'のBTCクローズ価格を予測します。' + '\n' | |
upOrDownRatio=predictionTommorow(data, trainDataLength, kyoushiDataNumber, predictionTrialTimes) | |
if upOrDownRatio>0.5: | |
outputStr += '\n明日のBTC価格は'+ str(round(upOrDownRatio*100,1)) +'%の確率で上昇します。' + '\n' | |
else: | |
outputStr += '\n明日のBTC価格は' + str(round((1-upOrDownRatio) * 100,1)) + '%の確率で下落します。' + '\n' | |
print(outputStr) | |
if(sendMailFlag): | |
subject='明日のBTC価格予想' | |
body=outputStr | |
sendMail(subject, body,yourGmailAddress,yourGmailAddressPassword) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment