ストックドッグ

KatoTakahiro。金融系の会社で働くSEが株やPython、その他諸々について書いています。サービスも運営してます→http://fmbrain.work

Pythonで機械学習を使った株価予測のコードを書こう

目次

はじめに

プログラミングを始めたばかりの人、機械学習を使って株価を分析してみたい人、このような人たちのために記事にしました。
少しでも助けとなれば私はうれしいです。

全てを読めば、株価を予測するためのコードを理解することができるよう心がけました。
理解することが大事なので、コードはシンプルにしてあります。

ひとつ注意点があります。
この記事を読むことで、株価を予測するためのコードは理解できるようになりますが、株価の予測はできません。
株価の予測は非常に難しいことであり、たくさんの工夫が必要です。
ただ、この記事は最初の一歩になると思います。
一歩さえ踏み出してしまえば、あとは各自で工夫していけるはずです。

ページの最後に本記事で使用したコードを掲載しています。

準備するもの

scikit-learn
pandas
ubuntu(OSは自由)
ネット回線

記事の流れ

  1. データ収集
  2. データの前処理
  3. モデルの学習
  4. 構築したモデルによる予測

予測手法

機械学習のランダムフォレストです。

ランダムフォレストは、調整が必要なパラメータが少なく過学習もしにくいため、機械学習の中でも扱いやすい部類に入ります。

かと言って、判別精度が悪いわけではないので非常に優秀な手法です。

ランダムフォレストについて詳しく知りたい方は以下の記事を参考にして下さい。

doz13189.hatenablog.com

データ収集

本記事で予測するのは、野村総合研究所(4307)の株価です。
以下のサイトで直近250日分のデータ(始値・高値・安値・終値出来高・売買代金)がダウンロードできます。
CSVと書かれている部分をクリックするだけです。

[4307 東証1部] 野村総合研究所 日足 時系列データ CSVダウンロード


次に説明変数となるデータを集めてきます。
野村総合研究所の株価を予測するには、野村総合研究所の株価データだけでは足りません。

では、何を集めてきたらいいでしょう?

まずは日経平均株価かな、次はTOPIX?あとドル円データも欲しいな…
あとは原油価格もあればうれしい、といろいろとあると思います。

あげだしたらきりがないし、正直それぞれ集めてくるの面倒くさいですね。
というか、こういうデータは自分で考えながら集めてくるものはありませんね。
集めれるだけデータを集めて、そこから説明変数として効果的なものを選びだすほうが効率が良いです。
少なくとも私はそうしています。

ということで、ここに載っているデータを適当に集めましょう。
ここにETF一覧が掲載されています。

stocks.finance.yahoo.co.jp

あれ?ETF??
私が探しているのは日経平均株価とか為替データで…

いいんです、ETFで。

ETFについて、とても軽く説明します。知っている方は読み飛ばして下さい。
ETFというのは、上場投資信託というもので、その名の通り投資信託が上場しているんです。
ヨーロッパ・アメリカでは有名な金融商品であり、最近は日本でも注目度が上がっている商品です。
投資信託と比べて色々とメリットはあるのですが、話が逸れそうなので詳しくは他のサイトに譲ります。

なぜ、ETFは説明変数候補として集めるかというと、指標と連動させている商品だからです。
例えば、日経225連動型上場投資信託
これは日経平均株価と連動するように運用されています。
そのため、日経平均株価を説明変数として組み込むのと、 日経225連動型上場投資信託を組み込むのは同じこと、になるんです。

ETFには様々な指標に連動させた商品があります。
上海株式、金、銀、原油、とうもろこしなどなど。
これらの指標は説明変数になりえます。

ということで、先ほどのETF一覧を見ながら、野村総合研究所の株価データをダウンロードしたサイトから集めてきましょう。

さすがに全部集めるのはしんどいので、適当に選びましょう。
ちなみに私は、

コード ETF
1309 上海株式指数・上証50連動型上場投資信託
1313 サムスンKODEX200証券上場指数投資信託
1314 上場インデックスファンドS&P日本新興株100
1322 上場インデックスファンド中国A株(パンダ)CSI300
1326 SPDRゴールド・シェア
1343 NEXT FUNDS 東証REIT指数連動型上場投信
1543 パラジウム上場信託(現物国内保管型)
1548 上場インデックスファンド中国H株(ハンセン中国企業株)
1549 上場インデックスファンドNifty50先物(インド株式)
1551 JASDAQ-TOP20上場投信
1633 NEXT FUNDS 不動産(TOPIX-17)上場投信
1673 ETFS 銀上場投資信託
1678 NEXT FUNDS インド株式指数・Nifty 50連動型上場投信
1681 上場インデックスファンド海外新興国株式(MSCIエマージング
1682 NEXT FUNDS 日経・東商取白金指数連動型上場投信
1698 上場インデックスファンド日本高配当(東証配当フォーカス100)

これらをダウンロードしました。

プラスアルファ
手動でデータを集めてくるのもいいですが、効率良く集めたいならスクレイピングがいいです。
現時点でスクレイピングがわからないという方は、「python スクレイピング]でググってみましょう。
思いの外スクレイピングが簡単にできることがわかると思います。
今回は、できるだけ記事をシンプルにしたいので余計な技術は使いません。

データが集まったらいよいよ前処理です。
前処理がおそらく一番難しくて、大変な作業です。
これさえ乗り切ってしまえばあとは楽勝です、がんばりましょう!

前処理

前処理ですること

  1. 野村総合研究所のデータと全てのETFのデータを統合して、ひとつの.csvにまとめる

まずは野村総合研究所の株価データを読み込んでみましょう。

import pandas as pd
df = pd.read_csv("code_4307.csv", header=0)
df.columns=["Date", "Open", "High", "Low", "Close", "Volume", "Trading Value"]
df["index"] = [i for i in range(len(df))]
print(df.head(10))

f:id:doz13189:20170209033100p:plain

人によっては、UnicodeDecodeErrorが出るかもしれません。
この原因は、ダウンロードしたcsvデータのcolumnsが日本語だからです。
csvデータの日付、始値、高値、安値、終値出来高の部分が文字化けしていると思うので、少し面倒ですがcsvデータからこれらを適当な英数字に修正しましょう。


さて、次のステップでETFのファイルを読み込み、それらを野村総合研究所の株価データと統合します。

そのために、まずETFのリストを作ります。
etf_listにダウンロードしたETFファイルのコードを入れましょう。

そして、ETFファイルの名前を「etf_1309.csv]にします。
ファイルの名前構成を「"etf_" + ETFコード + ".csv"」にすることで、ループ分を回した時にETFコードの部分を変えるだけで読み込むファイルを変えることができるようになります。

etf_list = [

1309,#上海株式指数・上証50連動型上場投資信託
1313,#サムスンKODEX200証券上場指数投資信託
1314,#上場インデックスファンドS&P日本新興株100
1322,#上場インデックスファンド中国A株(パンダ)CSI300
1326,#SPDRゴールド・シェア
1343,#NEXT FUNDS 東証REIT指数連動型上場投信
1543,#純パラジウム上場信託(現物国内保管型)
1548,#上場インデックスファンド中国H株(ハンセン中国企業株)
1551,#JASDAQ-TOP20上場投信
1633,#NEXT FUNDS 不動産(TOPIX-17)上場投信
1673,#ETFS 銀上場投資信託
1678,#NEXT FUNDS インド株式指数・Nifty 50連動型上場投信
1681,#上場インデックスファンド海外新興国株式(MSCIエマージング)
1682,#NEXT FUNDS 日経・東商取白金指数連動型上場投信
1698,#上場インデックスファンド日本高配当(東証配当フォーカス100)

]

さきほどの名前構成を変更したので、ループ分でetf_listに入っている全てのETFファイルを読み込むことができます。

for etf in etf_list:

	df_etf = pd.read_csv("etf_" + str(etf) + ".csv", header=0)
	df_etf.columns=["Date", "Open", "High", "Low", "Close", "Volume", "Trading Value"]


読み込むことができたら、次はETFファイルと野村総合研究所のデータを統合します。

統合する際に少し工夫が必要です。
ETFファイルは中身を見て頂ければわかると思いますが、穴ボコです。
NaNデータが多く、野村総合研究所のデータとそのまま統合すると、データの長さが異なるためズレて統合されてしまいます。

そのため、以下のコードでは野村総合研究所の日付をループ分で順番に取り出しながら、ETFファイルの日付に検索をかけます。
そして、日付が一致した日のETFのCloseデータを取り出します。
もし、そのCloseデータがNaNであった場合は前日のデータを代わりに入れています。

for etf in etf_list:

	df_etf = pd.read_csv("etf_" + str(etf) + ".csv", header=0)#データ読み込み
	df_etf.columns=["Date", "Open", "High", "Low", "Close", "Volume", "Trading Value"]#columns名を変更

	dates = []
	closeis = []
	for d in df["Date"]:
		date = df_etf.loc[(df_etf.Date == d), "Date"]#野村総合研究所の日付をETFファイルから検索
		yesterday_date = date.values[0]
		dates.append(date.values[0])#日付をデータセットに追加

		close = df_etf.loc[(df_etf.Date == d), "Close"]#日付が一致した日のETFのCloseのデータを取り出す
		if str(close.values[0]) != str("nan"):#取り出したCloseがnanでないかを判断
			yesterday_close = close.values[0]
			closeis.append(close.values[0])	

		else:
			closeis.append(yesterday_close)
		
	df_etf2 = pd.DataFrame({"Date_" + str(etf) : dates, "Close_" + str(etf) : closeis})#新しくデータフレームを作成
	df = pd.concat([df, df_etf2], axis=1)#野村総合研究所のデータとETFデータを統合

ETFデータは、Closeしか必要はありません。
しかし、プログラムでは日付データも一緒に追加しています。
これは、統合した後に目視で確認しやすいようにです。(出来上がったデータを見てもらえば、確認のしやすさがわかります)

よくデータ同士の統合で、データが一段ずれるなどのトラブルが起こります。
これはこういったトラブルを防ぐためのちょっとした工夫です。


さて、無事統合できました。
しかし、このETFデータにもうひと工夫する必要があります。

ETFのデータを階差系列に変更する必要があります。
このステップは非常に重要で、ETFの価格自体を説明変数として使っても、野村総合研究所の株価データは説明することはできません。
そのため、前日比などに変更する必要があります。

このコードをfor文の中に入れてやる必要があります。

df["diff_" + str(etf)] = (df["Close_" + str(etf)] / df["Close_" + str(etf)].shift(-1)) - 1

これで前処理は終了したので、新しくできたデータフレームをcode_4307_plus.csvとして保存します。

df.to_csv("code_4307_plus.csv")

モデルの学習

ここで新しくファイルを作成しましょう。

いよいよ機械学習で株価を予測します。

構築するモデルは、過去249日を学習して、250日目を予測するというものです。

import pandas as pd
from sklearn.ensemble import RandomForestClassifier


ETFデータを統合した野村総合研究所の株価データを表示しましょう。

df = pd.read_csv("code_4307_plus.csv")
df = df.sort_values(by=["index"], ascending=False)
print(df.tail(20))

ETFデータが全て統合されたデータが表示されたはずです。

このデータをテストデータとトレーニングデータにわけます。

df_train = df.iloc[1:len(df)-1]
#はじまりを[1:]としているのは、階差系列をとっているため[1]がNaNデータだからです。
#学習データにNaNデータがあると、エラーがでます。

df_test = df.iloc[len(df)-1:len(df)]
#テストデータには、一番最新のデータを入れます。

説明変数として使用するものをリストにしておきます。

xlist = [

"diff_1309",#上海株式指数・上証50連動型上場投資信託
"diff_1313",#サムスンKODEX200証券上場指数投資信託
"diff_1314",#上場インデックスファンドS&P日本新興株100
"diff_1322",#上場インデックスファンド中国A株(パンダ)CSI300
"diff_1326",#SPDRゴールド・シェア
"diff_1343",#NEXT FUNDS 東証REIT指数連動型上場投信
"diff_1543",#純パラジウム上場信託(現物国内保管型)
"diff_1548",#上場インデックスファンド中国H株(ハンセン中国企業株)
"diff_1551",#JASDAQ-TOP20上場投信
"diff_1633",#NEXT FUNDS 不動産(TOPIX-17)上場投信
"diff_1673",#ETFS 銀上場投資信託
"diff_1678",#NEXT FUNDS インド株式指数・Nifty 50連動型上場投信
"diff_1681",#上場インデックスファンド海外新興国株式(MSCIエマージング)
"diff_1682",#NEXT FUNDS 日経・東商取白金指数連動型上場投信
"diff_1698",#上場インデックスファンド日本高配当(東証配当フォーカス100)

]


ここで学習用のデータを作ります。
学習データの作り方は、x日のデータ(ETFの前日比)を説明変数に、x+1日の騰落を目的変数に入れます。
x+1日の株価が上昇していれば、+1を入れ、下落していれば-1を入れます。

x_train = []
y_train = []
for s in range(0, len(df_train) - 1):
	#print(df_train["Date"].iloc[s], df_train["Date"].iloc[s + 1])
	#print(df_train["Close"].iloc[s], df_train["Close"].iloc[s + 1])

	x_train.append(df_train[xlist].iloc[s])

	if df_train["Close"].iloc[s + 1] > df_train["Close"].iloc[s]:
		y_train.append(1)
	else:
		y_train.append(-1)

#print(x_train)
#print(y_train)

rf = RandomForestClassifier(n_estimators=len(x_train), random_state=0)
rf.fit(x_train, y_train)

n_estimatorsは、ランダムフォレストを構築するために生成する決定木の数です。
基本的には、データ数と同じにすれば大丈夫です。

コメントアウトしてあるprint文を表示してもらえば、一日づつズレて入っていることが解ると思います。

f:id:doz13189:20170209192840p:plain


では、最後に構築したモデルを使用して、株価を予測してみましょう。

データの中で一番最新のもの、つまり、2月7日のETFデータをtest_xとしていれます。

test_x = df_test[xlist].iloc[0]
test_y = rf.predict(test_x.reshape(1, -1))


f:id:doz13189:20170209204500p:plain

マイナス1が出たということは、2/8の株価は下落ということですね。

2月8日の株価を見てみましょう。

f:id:doz13189:20170209204350p:plain

下落しているので、予測は当たっていることになります。


以上で予測は終わりです。

もし、興味が湧いたという方がいればこのコードを少し修正して、他の日もシミュレーションをしてみると良い練習になると思います。

きっと散々な結果がでると思います。

もう一段ステップアップするには何をしたらいい?

ちょっと物足りないという人は他にも色々と試せることはあります。

  • 他の手法を試す
  • 数値を指数平滑化する
  • 過去249日で1日後を予測しているが、これが最適か考える
  • テクニカル指標など他の説明変数を試してみる

まとめ

とても簡単でしたね。

今は色々なパッケージがあるので、機械学習は簡単に扱うことができます。

案外簡単だったと思うので、この記事を機会に色々と勉強してみると面白いと思います。

今回使ったコード

ベタ打ちですみません。
ファイルは2つあります。

野村総合研究所のデータとETFデータを統合するためのファイル

import pandas as pd


df = pd.read_csv("code_4307.csv", header=0)
df.columns=["Date", "Open", "High", "Low", "Close", "Volume", "Trading Value"]
df["index"] = [i for i in range(len(df))]
print(df.head(20))

etf_list = [

		1309,#上海株式指数・上証50連動型上場投資信託

		1313,#サムスンKODEX200証券上場指数投資信託

		1314,#上場インデックスファンドS&P日本新興株100

		1322,#上場インデックスファンド中国A株(パンダ)CSI300

		1326,#SPDRゴールド・シェア

		1343,#NEXT FUNDS 東証REIT指数連動型上場投信

		1543,#純パラジウム上場信託(現物国内保管型)

		1548,#上場インデックスファンド中国H株(ハンセン中国企業株)

		#1549,#上場インデックスファンドNifty50先物(インド株式)

		1551,#JASDAQ-TOP20上場投信

		1633,#NEXT FUNDS 不動産(TOPIX-17)上場投信

		#1649,

		1673,#ETFS 銀上場投資信託

		1678,#NEXT FUNDS インド株式指数・Nifty 50連動型上場投信

		1681,#上場インデックスファンド海外新興国株式(MSCIエマージング)

		1682,#NEXT FUNDS 日経・東商取白金指数連動型上場投信

		1698,#上場インデックスファンド日本高配当(東証配当フォーカス100)

		]

for etf in etf_list:
	#print(etf)
	df_etf = pd.read_csv("etf_" + str(etf) + ".csv", header=0)
	df_etf.columns=["Date", "Open", "High", "Low", "Close", "Volume", "Trading Value"]

	dates = []
	closeis = []
	for d in df["Date"]:
		#try:
		date = df_etf.loc[(df_etf.Date == d), "Date"]
		yesterday_date = date.values[0]
		dates.append(date.values[0])

		close = df_etf.loc[(df_etf.Date == d), "Close"]
		if str(close.values[0]) != str("nan"):
			yesterday_close = close.values[0]
			closeis.append(close.values[0])	

		else:
			#print("nan")
			closeis.append(yesterday_close)
		
	df_etf2 = pd.DataFrame({"Date_" + str(etf) : dates,
							"Close_" + str(etf) : closeis})

	df = pd.concat([df, df_etf2], axis=1)
	df["diff_" + str(etf)] = (df["Close_" + str(etf)] / df["Close_" + str(etf)].shift(-1)) - 1
	#print(df)

df.to_csv("code_4307_plus.csv")


機械学習を行うためのファイル

import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score

df = pd.read_csv("code_4307_plus.csv")
df = df.sort_values(by=["index"], ascending=False)
print(df.tail(20))


df = df.iloc[0:len(df) - 1]
print(df.tail())

df_train = df.iloc[1:len(df)-1]
df_test = df.iloc[len(df)-1:len(df)]

#print("train", df_train)
#print("test", df_test)

xlist = [

		"diff_1309",#上海株式指数・上証50連動型上場投資信託

		"diff_1313",#サムスンKODEX200証券上場指数投資信託

		"diff_1314",#上場インデックスファンドS&P日本新興株100

		"diff_1322",#上場インデックスファンド中国A株(パンダ)CSI300

		"diff_1326",#SPDRゴールド・シェア

		"diff_1343",#NEXT FUNDS 東証REIT指数連動型上場投信

		"diff_1543",#純パラジウム上場信託(現物国内保管型)

		"diff_1548",#上場インデックスファンド中国H株(ハンセン中国企業株)

		"diff_1551",#JASDAQ-TOP20上場投信

		"diff_1633",#NEXT FUNDS 不動産(TOPIX-17)上場投信

		"diff_1673",#ETFS 銀上場投資信託

		"diff_1678",#NEXT FUNDS インド株式指数・Nifty 50連動型上場投信

		"diff_1681",#上場インデックスファンド海外新興国株式(MSCIエマージング)

		"diff_1682",#NEXT FUNDS 日経・東商取白金指数連動型上場投信

		"diff_1698",#上場インデックスファンド日本高配当(東証配当フォーカス100)

		]


x_train = []
y_train = []
for s in range(0, len(df_train) - 1):
	print("x_train : ", df_train["Date"].iloc[s])
	print("y_train : ", df_train["Date"].iloc[s + 1])
	print("")
	x_train.append(df_train[xlist].iloc[s])

	if df_train["Close"].iloc[s + 1] > df_train["Close"].iloc[s]:
		y_train.append(1)
	else:
		y_train.append(-1)

#print(x_train)
#print(y_train)

rf = RandomForestClassifier(n_estimators=len(x_train), random_state=0)
rf.fit(x_train, y_train)


test_x = df_test[xlist].iloc[0]
test_y = rf.predict(test_x.reshape(1, -1))

print("result : ", test_y[0])

クラウドファンディングの成功率ってどのくらい?徹底調査してみた

目次

クラウドファンディングとは?

クラウドファンディング(英語:Crowdfunding)とは、不特定多数の人が通常インターネット経由で他の人々や組織に財源の提供や協力などを行うことを指す、群衆(crowd)と資金調達(funding)を組み合わせた造語である。 ソーシャルファンディングとも呼ばれる。

近年多くの注目を集めており、大きな資本を持っていなくてもアイデアや技術を売りに資金を募ることができます。

個人やベンチャーからすると、大きな参入障壁である「資金」という壁を取っ払うことができる革新的なサービスです。

キングコング西野さんの絵本や堀江さんのロケットなどはマスコミ含め大きな話題を読んでおり(炎上も含め)、かくいう私自身もクラウドファンディングを利用しています。

私が立ち上げているのプロジェクトはこちら!
camp-fire.jp

年々支援額は伸びており、今後が非常に楽しみな分野であります。

日本の有名ドコロは?

camp-fire.jp

現在、日本のクラウドファンディング業界のトップを走るのがCAMPFIREです。

なんと言っても圧倒的な手数料の低さ。引くほど低い。

シェアを見ても、52%と2位に倍の差をつけていますね。(2017年1月時点)

もうすでにニッチ戦略に走っている他のクラウドファンディングサイトもあり、業界内の勝負は決まったかな、と思えるほどの独走ぶりです。

クラウドファンディングはじめるならCAMPFIRE、と言える状況ではありますが、それでもクラウドファンディングをはじめてさらに他人から資金を援助してもらおうと思うと苦労は多いです。

ということでCAMPFIREを徹底調査し、

どんなプロジェクトにどのくらいお金が集まっているかを調査します!

調査方法は、CAMPFIREのサイトに掲載されている全てのプロジェクトの支援総額と支援者人数を集計し、それらをカテゴリごとに平均、一人あたりの平均支援額などを計算しました。

注意点として、CAMPFIREのサイトに掲載されており、かつSUCCESSしているプロジェクトが対象という点です。

※支援額がプロジェクトの目標金額に達することをCAMPFIREではSUCCESSと言う


プロジェクトは立ち上げても、必ずCAMPFIREのサイトに掲載されるわけではありません。

注目度や内容を加味して、CAMPFIREの運営者がサイトに掲載するかどうかを決定するみたいです。

そのため、掲載されているものは人気なものが多いです。

人知れず、目標金額に届かずに消えていくプロジェクトは多数あるとは思いますが、それらはなかなか調べることはできません。(CAMPFIREにはデータとして蓄積されているでしょうが...)

調査結果

CAMPFIREにはカテゴリが存在します。

プロジェクトがどのカテゴリに属するかを表しています。

カテゴリ一覧
アート、音楽、演劇・ダンス、プロダクト、テクノロジー、ゲーム、ジャーナリズム、コミュニティ、フード、写真、ファッション、映画・映像、本・漫画、アニメ、パフォーマンス、スポーツ、ビジネス、お笑い・ネタ、ソーシャルグッド


支援総額が大きいプロジェクトランキングTOP10

順位 カテゴリ 支援総額 支援者人数
1 アート 46,373,152円 6257人
2 プロダクト 30,455,500円 1250人
3 コミュニティ 27,040,400円 141人
4 スポーツ 20,209,000円 473人
5 プロダクト 15,043,000円 244人
6 ミュージック 14,826,200円 693人
7 ビジネス 13,646,000円 254人
8 ミュージック 11,855,553円 754人
9 プロダクト 10,611,600円 269人
10 ソーシャルグッド 10,007,091円 2,974人

一位はなんと5000万近く集めているようです。驚愕。

トップ10は一本超えのモンスター級ばかりが並んでいますね。



平均支援額・平均支援者人数

プロジェクト一本あたりの平均支援額、平均支援者人数を見てみましょう

平均支援額 平均支援者人数
1,051,861円 99人

ひとつのプロジェクトを立ち上げた時、平均で100万円くらい集まり、平均して100人くらいの人が支援をしてくれることになります。

これはあくまでも平均です。

キンコン西野さんや堀江さんなどの化物プロジェクトが平均を大きく釣り上げています。


気になるプロジェクト成功率

一体クラウドファンディングを立ち上げた際の成功率はどのくらいなのでしょうか?

しかし、プロジェクト成功率は公表されていません。

そのため、プロジェクト成功率は私自身の予測であり、正式な数値ではありません。

ただ、けっこうな妥当な数値かなぁ、と思います。


サイトに掲載されており、SUCCESSしているプロジェクトは1117件でした。

そして、CAMPFIREがいかにすごいかを自慢しているページに、「19カテゴリで4200件以上」のプロジェクトが立ち上がっていることが書かれています。

camp-fire.jp

この4200件という数値はおそらく成功or失敗に関わらない全てのプロジェクト数だと思われます。

ということは。

SUCCESSプロジェクト数1117件 ÷ 全プロジェクト数4200件 = 26%

プロジェクトの成功率は26%ということになります。


予想より高いですね...

ただ、気をつけたいのはCAMPFIREではプロジェクトを立ち上げる前に、プロジェクトの審査があります。

審査に通過したものでないと、プロジェクトとして立ち上がりません。

もし、この成功率があっていたなら、審査を通過してもなお、4分の1しかプロジェクトは成功しないことになります。


支援額を可視化

f:id:doz13189:20170125211828p:plain

これは、横軸に支援額、縦軸にプロジェクト数をとったグラフです。

可視化する際に、支援額の大きいプロジェクトの上位20位くらいを省いています。

でないと、1番支援されているものは5000万ほどだったので支援額の小さいものがグラフで目視できないレベルに押し込められてしまいます。


100万円以下がかなり盛り上がっていることがわかります。

大きなプロジェクトを除けば、だいたい平均支援額は60〜80万くらいになりそうです。


支援者の人数を可視化

f:id:doz13189:20170125212704p:plain

縦軸にプロジェクト数、横軸に支援者数をとっています。

こちらも100人以下が盛り上がっており、支援者は40人程度のプロジェクトが一番多いようですね。

グラフの横軸にpatronと書いてあるのは、CAMPFIREでは支援者のことをパトロンと呼ぶからです。


支援者と支援額の関係を可視化

f:id:doz13189:20170125212939p:plain

縦軸に支援者数、横軸に支援額をとっています。

散布図は右に流れていっていますね。

このことから、だいたい支援者数100人くらいからは伸びづらくなっていることがわかると思います。

なので、支援額が大きいプロジェクトを立ち上げる際は、支援者を増やすというよりかは、一人あたりの支援額を伸ばすことを意識した方が良いということが言えますね。


カテゴリごとの平均支援額

f:id:doz13189:20170125213720p:plain

画像小さくてすみません、右からアート、音楽、演劇・ダンス、プロダクト、テクノロジー、ゲーム、ジャーナリズム、コミュニティ、フード、写真、ファッション、映画・映像、本・漫画、アニメ、パフォーマンス、スポーツ、ビジネス、お笑い・ネタ、ソーシャルグッド、です。

ダントツの一位は平均160万円のアニメでした。

パフォーマンスは平均30万ほどで、最下位でした。

この数値は、良く支援されているか否かを表すものではありません。

「アニメ」は制作にそれだけコストがかかるため平均支援額が大きく、「パフォーマンス」は比較的安価であるということを意味しています。


もし、これからクラウドファンディングをはじめる方がいればこの数値は大いに参考になるはずです。

例えば、アニメを作ろうとした時、目標金額を200万にすると他のプロジェクトよりもかなり高くなります。

そんなにアニメ作るのにお金いるの?と支援者が疑問に思ってしまうと支援はなかなかもらえません。

もし、無難に支援を集めたいなら平均を大きく超える目標金額の設定は控えたほうが良いと思います。


もちろん、プロジェクトによって必要な支援が額はまちまちなので、あまり平均にとらわれる必要はありませんが。


カテゴリごとのプロジェクト数

f:id:doz13189:20170125214722p:plain

これはカテゴリごとのプロジェクト数を可視化しており、どのカテゴリでのプロジェクト立ち上げが多いかがわかります。

音楽は200件、ソーシャルグッドは150件と多いです。

コミュニティも100件ほどありますね、地方創生が活発であることが見てとれます。


アニメ、テクノロジー、コメディが10件程度と少ないですね。

この2つのプロジェクトは成功率が低いから成功数も低いのか、はたまた、異なるクラウドファンディングサイトでのプロジェクト立ち上げが多いのか。

もし、後者であればCAMPFIRE運営の課題でもありますね。

たしか、アニメ専門のクラウドファンディングがあったと思うので、もしかしたらそちらに流れているのかも。


この可視化で、どのカテゴリが盛り上がっているかがわかりますね。

プロジェクトの成功率は、このプロジェクト本数とある程度比例するんじゃあないでしょうか。

支援する人は自分の好きなカテゴリを選ぶことが多いので、CAMPFIREではミュージックに関心がある支援者が多い、ともとれます。


カテゴリごとの一人あたり支援額

f:id:doz13189:20170125215650p:plain

だいたい1万円くらいが平均みたいです。

アニメを除けば、ほかはあまりカテゴリごとに偏りはなさそうですね。

以上が集計結果でした

資金のない個人、ベンチャーからするとクラウドファンディングは夢を叶えるチャンスを大きく広げるサービスです。

ただ、多くのプロジェクトを見ると、立ち上げている本人のワクワクは伝わってくるものの、大切な資金の使い道やなぜ必要なのか、プロジェクトの魅力が十分に伝わっていないものも散見されます。

人から支援を受けるには、ワクワクだけでは足りないのが事実です。


私も立ち上げた経験があるので、とてもワクワクする気持ちはわかります。本当にワクワクします。プロジェクトを友達に告知するのが楽しくて楽しくて仕方がありません。

ワクワクは悪くはないのですが、少し冷静になって分析することは大切かなぁ、なんて思います。

そういった時に、どのくらいの規模のプロジェクトが成功しやすいのかや、どのくらいの支援者を目標にすればいいか、などの目標設定や分析に今回の調査結果を使用していただければ幸いです。

お金が足りない...はもう言い訳にならない

成功率は4分の1程度と調査結果を発表しました。

プロジェクト審査含めの成功率4分の1ですが、資金を集めるハードルは以前より格段に下がっているでしょう。

学生でも20代でも団塊の世代でも誰でも挑戦できるのがクラウドファンディングの良いとろこです。

どんどん挑戦しましょう!

この記事を読んだことを機会に、クラウドファンディングをやってみよう、と思ってくれる人がいれば私はとても嬉しいです。

一人でも多くの人がクラウドファンディングで何か楽しいことに挑戦することで日本の将来は明るくなっていくと思います!!

最後に告知(2回目だけどワクワク)

camp-fire.jp

こんなプロジェクトを立ち上げています。

もし、内容を読んで支援してやってもいいぞ、という方は支援をよろしくお願いします。

終わり!

本記事の調査方法(コード記載あり)

PythonライブラリのBeautifulSoup4でサイトから数値をスクレイピングさせてもらいました。(サーバーに負荷かけてすみません)

スクレイピングした数値をpandasで計算しています。

以下が使用したコードです。(ベタうちですみません)(スクレイピングに使用したコードのみ)

スクレイピングする際は、time.sleep(1)で相手サーバーに配慮しましょう!!

import requests
from bs4 import BeautifulSoup
import time
import pandas as pd


#CAMPFIREのプロジェクトの分類
category_box = ["art", "music", "dance", "product", "technology", "game", "journalism",
			"community", "food", "photo", "fashion", "movie", "publishing",
			"anime", "performance", "sports", "business", "comedy", "social-good"]


money_list = []
patron_list = []
category_list = []


#CAMPFIREのサイトは、分類ごとに分かれている
#URLの一番右を見ればそれがわかる
#この分類ごとにページをクローリングする
#https://camp-fire.jp/category/art

for category in category_box:

	page = 1
	while True:

		time.sleep(10)

                #分類ごとのURL作成
		url = "https://camp-fire.jp/category/" + str(category) + "/most_funded/page:{0}"

                #CAPFIREのサイトにリクエストを送り、レスポンス(サイト情報)を受け取る
		r = requests.get(url.format(page))

                #分析が可能な形に変換
		soup = BeautifulSoup(r.content, "html.parser")

                #各プロジェクトは、<div class="overview">に囲われている
                #ページ内のプロジェクト数がゼロであれば、while文をbreakする
		if len(soup.select(".overview .total")) == 0:
			print(len(soup.select(".overview .total")))
			break

                #各プロジェクトの情報を取得
                #取得する情報は、「SUCCESS」かどうか、現在集まっているお金、パトロンの人数
		for money, patron, success in zip(soup.select(".overview .total"), soup.select(".overview .rest"), soup.select(".success-summary span")):
			print(success.string)
			if success.string == "SUCCESS":

				money_split = str(money).split("</small>")
				money_split_split = money_split[1].split("円")
				money_processing = money_split_split[0].split(",")
				real_money =  "".join(money_processing)

				print(real_money)
				money_list.append(real_money)

				patron_split = str(patron).split("</small>")
				patron_split_split = patron_split[1].split("人")
				patron_processing = patron_split_split[0].split(",")
				real_patron = "".join(patron_processing)

				print(real_patron)
				patron_list.append(real_patron)

				category_list.append(category)

				print("----------------")
		page += 1

#CSVに出力するためにDataFrame形式にまとめる
df = pd.DataFrame({"money" : money_list,
					"patron" : patron_list,
					"category" : category_list})

df.to_csv("campfire.csv", index=False)

予測精度向上のための次なる手 〜クラウドファンディングはじめました〜

f:id:doz13189:20170120173259j:plain

目次

この記事は前回の続き

前回までのあらすじはこの記事。

doz13189.hatenablog.com

前回のシミュレーション結果を踏まえて、熟考と改善を重ねた結果

予測精度が上がりました!

予測する銘柄数を大幅に減らしました

336銘柄ある中から、予測しやすそうな銘柄のみを厳選し...

さらに説明変数の選び方も少しいじって...

株価の騰落予測を過去12ヶ月分シミュレーションし直してみると...

なんと62.78%まで向上しました。

予測している銘柄少なすぎる問題が発生

前回までは、300ちょいある中からだいたい60銘柄ほどをチョイス。

今回は、さらに減って10ちょいくらいの銘柄数しか予測できていません。

厳選した分は、上がったので良かったですが...

シミュレーション結果

予測月 : 12 月
対象銘柄数 : 6
予測的中銘柄数 : 4
予測精度:66.6%

予測月 : 11 月
対象銘柄数 : 8
予測的中銘柄数 : 5
予測精度:62.5%

予測月 : 10 月
対象銘柄数 : 15
予測的中銘柄数 : 11
予測精度:73.3%

予測月 : 9 月
対象銘柄数 : 7
予測的中銘柄数 : 4
予測精度:57.1%

予測月 : 8 月
対象銘柄数 : 11
予測的中銘柄数 : 6
予測精度:54.5%

予測月 : 7 月
対象銘柄数 : 12
予測的中銘柄数 : 4
予測精度:33.3%

予測月 : 6 月
対象銘柄数 : 11
予測的中銘柄数 : 5
予測精度:45.4%

予測月 : 5 月
対象銘柄数 : 15
予測的中銘柄数 : 12
予測精度:80.0%

予測月 : 4 月
対象銘柄数 : 21
予測的中銘柄数 : 16
予測精度:76.1%

予測月 : 3 月
対象銘柄数 : 9
予測的中銘柄数 : 3
予測精度:33.3%

予測月 : 2 月
対象銘柄数 : 8
予測的中銘柄数 : 7
予測精度:87.5%

予測月 : 1 月
対象銘柄数 : 6
予測的中銘柄数 : 5
予測精度:83.3%

平均予測精度は、62.78%

はてなのテーブル作るのめんどくさすぎるので、プログラムで出力している形のまんまで出しました。

いぜん安定せず...

前回のシミュレーション結果を見ると、ボラティリティの大きい月の予測精度が比較的悪かった印象がありました。

例えば、1月、3月、6月、7月、11月...


何かしらのイベントによる影響が株価を動かしていたこともあり、予測はしづらい月であることは間違いないのですが、そういった月も予測できてやっとはじめて実用的になると思うので、何とか工夫して予測精度が改善できないかを考えていました

なので、説明変数を仕分けしながらボラティリティが大きい時に効くものをチョイスして、ランダムフォレストのモデルを構築しなおしました。


予測精度は改善はしたのですが、予測のしづらい月は相変わらず予測精度50%を切る結果となりました。

最近は、新しいデータを加えるというよりかは、中身のアルゴリズムをいじって改善を試みています。

しかし、今持っているデータでは限界かな、と思えるような結果しか出ないです...

結局、今回もボラティリティが大きい月は50%を下回る予測精度しか出なかったです。(前回、50%を下回った月とほぼ同月)

クラウドファンディングはじめました

SNS等では告知しているのですが。

camp-fire.jp

四季報yahoo!ファイナンスVIP倶楽部のデータが使いたくて、その資金を集めるためにクラウドファンディングをはじめました。

予測精度向上のための次なる手です。

資金が集まらなくて苦労はしていますが...

もし、よければご支援下さい涙

誰かァァァあぁ、支援をぉぉ涙涙涙

おまけ

空き時間を見つけては、「株価 機械学習」とかいろんなワードでググったり、twitterで検索しながら何か参考にできる情報がないかを探索しています。

f:id:doz13189:20170120172407p:plain

このツイートを見つけて、めちゃめちゃ共感しちゃいました。

株価予測をするときに、「未来のデータを参照」はもうホントあるある探検隊です笑

一回私もやらかしましたからね...

見つけた時の絶望感半端ないです。

pandasでデータをくっつけるときによく起こりがちな事故なんですよね。


それからは、DataFrame同士をくっつける時に、いっしょに日付データも入れるようにして再発防止をしています。

なので、統合したDataFrameはくっつけた分だけ日付データがあります笑

ただ、目視での確認がとてもしやすいです。

ドルと日経平均とユーロをくっつけたDataFrameはこんな感じです。

f:id:doz13189:20170120173820p:plain


今作っているデータには未来のデータ参照はおそらくないと思います。(おそらく)(何回も確認しています)

未来のデータを参照した時って、めっちゃ安定するんですよね、精度が。

そういった意味では、今回のシステムの精度は分散激しいし、むしろ50%下回っている月もあるのでかえってリアリティ増しているのかなぁなんて思っています。

機械学習で株価を予測(まとめ) 〜平均予測精度57%〜

f:id:doz13189:20170115152013p:plain
過去1年の株価予測シミュレーション結果

目次

この記事はまとめ記事です

去年の11月頃から機械学習を使用した株価の予測をやっています。

新しい結果や発見があるたびにポツポツと記事にしていたのですが、見る人からすると断片的すぎてわかりづらいと思うので、今日まとめの記事を作ることを決意しました。

この記事を読んでわかること

  • 私について。
  • 予測に使用している機械学習の手法
  • 予測に使用している説明変数
  • 予測精度は上がるかわからないけど、予測はしているモデルの構築の仕方
  • 参考にした本やサイトたち

予測精度をそれなりに上げるには適当に機械に学習させるのではなくて、ちょっとだけ工夫がいります。

この記事に書いてあることを参考にすれば、予測精度はどうなるかわかりませんが、予測をするモデルの構築の仕方はわかると思います。(コードは載せてませんが、scikit-learnの実装はとても簡単なので載せる必要もたぶんないです、ぐぐったらたくさんコードでてきます。)

ちょっとの工夫についてはぼかしながら書きますが、この記事をちゃんと理解できる人は100%私より頭が良いので、私のざっくりとした説明を読んで、それぞれで工夫をすれば、それなりの精度の予測モデルを構築できるようになるはずです。

この記事は、ランダムフォレストで株価を予測する際に気をつけるべき点を充填的に書いています。

私がここ2、3ヶ月の間、おそらく総プレイ時間300時間超で発見したことをガンガンと書いているので、もし、私と同じことをしようとしている人がいれば、参考になる内容じゃあないかなぁ、なればいいなぁという心意気な具合です。

まず自己紹介

バイトで貯めた、なけなしの金25万を手に去年の6月頃からスイングトレードを主に株を始めました。
と同時にプログラミングも開始(Python)。まだまだぺっぽこプログラマー

プログラミングと株をはじめてから半年経つか経たないか瀬戸際の頃、株もプログラミングも入門レベルくらいに達していました。独学も何だし地元のPython勉強会に参加しました。これが良い転機に。
その時に参加されていた方(この本の著者)にこんな記事あるよ〜って教えてもらいました。

その時教えていただいた記事がこれ
masamunet.com

わお、機械学習ってこんなことできんのかよ!?って思い、こんなことやってみたい!と感じ、脳筋の私はその驚きの勢いのまま次の日から「機械学習で株価を予測」の旅をはじめました。

そこからです、辛い日々は。

目を充血させながら毎日毎日PCと向き合い、エラーが出るたびに泣きそうになり、まったく予測精度も上がらず眠れない夜が続き、やっぱり簡単じゃあないなぁ、無理かなぁ、なんて思いながら諦めるには時間を費やしすぎていて悔しかったので、諦めずに前を向き続けながら、順調にメンタルはボロボロになっていき、やっとの思いである程度の形のものを作ることができました。

ちょうど卒論の時期とかぶっていたのですが、卒論そっちのけで株価予測をやっていたので、かなり教授に嫌われ、現在は絶交状態です。ゼミ中に私が教授に話しかけるとそれだけでピリッとした空気になるので、その空気を一瞬で出せる教授はやっぱりすごい人だと思います。

そもそも株価の予測って何?どうやるの?

この記事を読んでいる人はきっとインテリなんで、もはや私ごときが説明するのも恐縮なんですが、半年前の私みたいにプログラミング楽しそ〜って目をキラキラさせている人がこの記事を読んでくれたときのためにザックリと説明しておきます。

機械学習(ランダムフォレスト)を使用して予測しています。
さっきから予測予測と言っていますが、行っていることは分類です。


今後株価が

  1. 上がる銘柄
  2. 下がる銘柄

この2つに分類しているんですね。


この2つに分類するために、過去4年間の株価データ・為替・経済指標を使用しています。

機械学習には教師データというものが必要であり、その教師データが過去4年間の株価データ・為替・経済指標です。

これら教師データから傾向などを学習していき、分類モデルを構築します。

構築したモデルによって、1ヶ月後の株価が上昇するのか、あるいは下落するのか、に分類します。

分類した結果=予測結果であり、このような流れで株価を予測しています。

もう少し詳しく

今回、予測は1ヶ月単位で行っています。

なので教師データも1ヶ月単位です。


f:id:doz13189:20170115144305p:plain


これがデータセットの基本的な形です。

画像のデータセットには、始値終値出来高とかしかありませんが、これを基本に様々な経済指標や為替を追加していくことで教師データを作っていきます。

どんなデータを追加するかは、「説明変数一覧」を下に載せているのでそちらを参照してください。


機械学習(ランダムフォレスト)には目的変数と説明変数が存在します。

目的変数=yには何を入れるか。

ここに1ヶ月後株価が上昇したのか、下落したのかを入れます。

そして、説明変数=xに経済指標や為替などを入れます。

ここでの説明変数の意味合いは、経済指標や為替がどれだけ1ヶ月後の株価の上昇・下落に影響を与えているか、ということを説明するための変数であると言えます。

つまり、xには1ヶ月後の株価の上昇・下落に関わってそうな変数を選んでくることが重要となります。

例えば、2016年10月の教師データを見てみると。

yには2016年11月の株価が上昇したか下落したか
xには、2016年10月の経済指標・株価データ・為替

このようにyとxは1ヶ月分ズレながら学習させていくことになります。

そして、学習モデルを構築し終われば、予測したい月の前の月のデータをxに入れます。

そうすることでyには、上昇するのか、下落するのか、という予測結果が入ります。

現在であれば、2016年12月のデータをxに入れると、2017年1月に株価が上昇するのか、下落するのかを予測してくれます。


先ほど、yには株価の上昇・下落を入れるとサラッと言いましたが、ここは少し工夫が必要です。

機械学習(ランダムフォレスト)では2値が扱いやすいので、1ヶ月後に上昇していたら1、下落していたら0とすればいいのですが、これではあまり上手く行きません。

なぜなら、ちょっと株価がちょっと上がっても1になり、ちょっと下がっても0になるからです。

ちょっと上がった株価は、上がるべくして上がったのか言われると怪しいですね。

つまり、ちょっと上がった株価には上がるに値する特徴があまりありません。

それにも関わらず、ちょっと上がった株価まで含めて学習させてしまうと間違ったことを学習させてしまう危険があります。

それを回避するために、上昇・中間・下落の3つに分けます。

この分け方は、独自で考えてもらえばいいのですが、私は次の月の騰落率が

+1%<=上昇
+1%>中間>-1%
-1%>=下落

このような形で分類し、上昇であれば1を、下落であれば0を入れています。

そのため、48ヶ月分のデータを使用していますが、中間に含まれる月は省くので48個よりデータは少なくなります。

そして、教師データには上昇と下落のみを使用します。

予測手法

先ほどからちょろっと言っていますが、使用しているのはランダムフォレストです。

オリジナルの記事では決定木を使用しているのですが、決定木の深さや葉の数など調整はめんどくさいです。

そもそも私は決定木スペシャリストではないので、葉や深さの調整方法もあまり知りません。記事では一番最適な深さ、葉の数を見つけており、私もその方法で一度やってみたのですが、そもそも決定木の分類精度が低いので調整をしたところで目くそ鼻くそな結果しか得られませんでした。

しかも、株価の説明変数なんてたくさんありすぎて、これらを決定木で分類しようとしても過学習待ったなしです。

これが決定木を諦めた一番大きな原因でした。


もう決定木の分類精度は低いということは潔く認めてしまって、決定木をたくさん集めたランダムフォレストを使用してみようという結論になりました。

いくら一つ一つが弱いと言えども、決定木を集めれば立派な分類器が作れるんじゃないか、というのがランダムフォレストの考え方です。

ものすごく性能の良いガンダムを一つ生産するよりも、性能は落ちるけどジムを量産したほうが強いんじゃないか?という考え方とすごく似ています。

ランダムフォレストは素人から玄人までみんなに愛されているジムキャノンのようなやつで、扱いやすいのが特徴です。

調整が必要なパラメータは、何個の決定木からランダムフォレストを生成するか、だけです。

一般的には、このパラメータは個数に比例して、性能は安定し、それと引き換えに計算のコストは増えます。

よっぽどPCがへっぽこじゃなければ、計算コストはあまり心配しなくても大丈夫です。

他にもざざっとランダムフォレストの特徴を上げておきます。


メリット

  • 説明変数が多数であっても、性能が安定する
  • 学習・評価が高速
  • 説明変数の重要度が算出可能(ホワイトボックス)
  • 交差検証法での評価が可能


デメリット

  • 重要度の高い説明変数が少なく、ノイズ変数が多いとランダムフォレストの性能が安定しなくなる


ホワイトボックスというのがとても重要です。

なぜなら工夫ができるからです。

メンタルにはこたえますが、なぜ上手くいっていないのかが究明できます。

説明変数の重要度を見たりしながら考えては工夫してという工程を繰り返すことで少しづつ予測精度が上がっていったので、もしこれがブラックボックスであれば、諦めるしかなかったと思います。

ディープラーニングもいいですが、中身でどういった処理をしているのかがわかるというのは、想像以上に重要なことだと私は考えます。

決定木についておさらい

ランダムフォレストを使用する上で、決定木の理解は欠かせません。

あくまでもランダムフォレストは決定木の集合体なので、決定木の分類の仕方を把握しておかないと、出力された結果を上手く把握することができません。

インテリな人は読み飛ばしてください。

ザックリと決定木の分類のイメージを説明します。

f:id:doz13189:20161207215442p:plain

決定木の処理の中身はこのような形になっています。

一つの質問ごとにYESとNOで分けていき、どんどんと枝分かれをしていきます。

この枝分かれする際は、ジニ係数を使用しています。

Scikit-leanはデフォルトでは、ジニ係数を使用しており、指定すればエントロピーも使用可能です。

このYESとNOで分けているという部分がものすごく重要なんです。

そして、このYESとNOに分ける際は、大なり小でわけます。

A <= B

この式が基本であり、もしAよりBが大きければYESに、小さければNOに、という分け方です。

この式を繰り返し行うことで、複数に枝分かれしていきます。

これこそが株価を予測する上で核となる部分です。

例えば、説明変数に日経平均株価を選んだとします。

すると

日経平均株価17000円 <= B

この式が出来上がったとします。

すると、決定木は日経平均株価17000円以上ならBは今後上昇し、17000円以下ならBは今後下落するという判断を行うことになります。

このように単純に日経平均株価を説明変数として入れると、こうなりますが、これでは上手く分類は行えません。

もし、この式が正しければ、1万円を常に割っていた民主党政権時代は永遠に株価が下がり続けることになります。

日経平均株価の価格自体には株価の上昇下落は説明することができません。

なので例えば、日経平均株価の騰落率に変換したりなどという工夫が必要になります。


これは他の指標にも言えることです。

あくまでもYESかNOの形に落とし込んだ時に、上手く分類を行える指標でなければ上手く行きません。

上手く行く例として、例えば、米国の失業率を入れたとします。

5%以下なら株価は上昇し、5%より大きいなら株価は下落する、というルールが出来上がり、これは未知データにも有効に効くルールとなります。

このことを理解して、説明変数を選ぶ必要があります。

ランダムフォレストも万能じゃない

ランダムフォレストは過学習には陥りにくいですが、じゃあ何個説明変数をぶち込んでも大丈夫かと言われるとそうではありません。

ランダムフォレストを生成する際、何個も決定木を生成するのですが、その決定木はどうやって生成するのでしょうか?

これは用意された説明変数からランダムに選んで、選ばれた説明変数で決定木を生成します。

これを何回も繰り返して、フォレストを構築するのですが、選ばれた説明変数がノイズ変数ばかりだと、へっぽこ決定木ばかりを生成することになります。

※ノイズ変数というのは、株価の騰落に何ら影響を与えていない変数。例えば、その日くしゃみをした人の数などは何ら株価に影響を与えません。

へっぽこの決定木を集合させても、ランダムフォレストの性能は良くなりません。

なので、ノイズ変数は出来る限り減らしたほうがいいです。

clf.feature_importances_

このコードで説明変数の重要度は確認することができます。

一通り説明変数になりそうな数値を集めてきたら、これを見ながら、ガツガツとノイズ変数を減らし、良いランダムフォレストを構築しましょう。

ただ、気をつけてほしいのは重要度が高ければ株価の分類に役立っているかというとそうではないことがあります。

低いのはザックザク切って構いませんが...

試しにドル円レートを説明変数に突っ込んでみるといいです。

重要度はそこそこを示しますが、ドル円レートは未知データに対して何ら威力を発揮しません。

過去を見ると、偶然的にドル円112円以上なら株価が上がって、以下なら株価が下がって、というパターンがあります。

こういうパターンを見つけて、モデルは学習しますが、そんなルールは存在しないので未知データを与えた時、このルールを元に判断しても精度は上がりません。

このようなことはたくさんあるので、未知データに効いているか否かはちゃんと調べないといけません。


もうひとつ、説明変数が多すぎると生じる弊害を書きます。

それは説明変数同士で矛盾が生じるからです。

これは説明変数同士の重要度がさほど変わらないが故に起こる問題なのですが、例えば、説明変数に米雇用統計とドル円レートを選んだとします。

もし、米雇用統計は良い数値を出している、がしかし、ドル円レートは円高...

こうなったとき、決定木はどう判断するでしょうか。

正直、人間でも判断しかねる状況...

もちろん、決定木では過去データからジニ係数のより低い方を先に説明変数として選ぶことになります。

ただ、残念なことにこれは上手く行きません。

判断はするのですが、この方法では精度が上がりません。


こういった矛盾は説明変数の数が多ければ多いほど起こりやすくなります。

出来高は増えているのに、日経平均株価は下がっていて、でも、消費者物価指数は上がっていて、などなどが同時多発でおきます。

こうなると、もう来月上昇するのか下落するのか上手く分類を行うことはできません。


私の経験からするとどんどん予測精度が50%に近づいていきます。

【訂正】
↑これは怪しい!ちゃんと検証して見る必要があるかもしれない。

もともと2値なので、適当にしても50%です。

つまり、適当に答えているのと同じになってしまいます。

株価はそのときどきによって、大きく影響が受ける変数が異なります。

ある月は、米雇用統計に素直に反応したり、ある時は、ドル円レートに素直に反応したり。

このようなことがあるので、株価を予測する際、説明変数は出し入れすることが効果的です。

出し入れの方法は各自で考えてもらうとして、ざざっと使用した説明変数の一覧をのせませう。

説明変数一覧

NT倍率
出来高
日経平均株価
ドル円レート
ユーロ円レート
TOPIX
ポンド円レート
売残
買残
売残増減
買残増減
信用倍率
上海株式指数
東証REIT指数
JASDAQ
インド株式指数
海外新興国株式
消費者信頼感(速報値)
失業率

これだけじゃあ、ありませんがどんな説明変数を使用しているかわかっていただければ、あとは自分で探してこれると思います。

ただ、これらを使用するだけでもけっこうな予測精度は出ると思います。

ためしにやってみたところ、これだけでは散々な結果しか得られません!

これらの説明変数にもうひと工夫しましょう!!

過去1年間のシミュレーション

2016年1月から2016年12月の計12ヶ月分のシミュレーションを行いました。

12月 69.70%
11月 59.32%
10月 72.84%
9月 61.90%
8月 29.49%
7月 26.97%
6月 67.86%
5月 61.54%
4月 63.77%
3月 36.37%
2月 78.57%
1月 55.56%

平均予測精度57.01%

ただし、これは情報落ちが激しい数字です。

予測精度の分散が大きいので、あまり鵜呑みにできない数字。

予測できている月はそこそこの精度がでていますが、外れている月はへっぽこです。

予測精度がへっぽこの月は、選んできた説明変数以外の変数が株価に大きく影響を与えている証拠です。

もし、株価に影響を与えると考えうる全ての説明変数を選んでくることができれば、こういったことは少なくなるはずです。(なくなることはないと思います、予測外は必ず起こるので)

また、11月は大統領選挙があったにも関わらず的中率が下がっていません。

これに関しては、全くの偶然であると考えています。

予想外のことが逆の方向に働かなかっただけです。

上昇を予測しているのに、予想外にも急落すれば的中率は下がりますが、上昇を予測して、予想外にさらに上昇すれば、そこまで的中率は下がりません。

決して、トランプ相場を予期していたわけではありません。

予測と逆のことが起きている月は順調に(?)予測精度が低いです。


これらを含めて、平均すると57%の確率で予測は当たるということになります。


月の予測結果詳細は以下に掲載します。

予測結果詳細には注目すべきデータがあります。

それは予測上昇下落銘柄数と実際上昇下落銘柄数です。

この数は、かなりの精度で近似しており、この数値自体を活用できるんじゃないかと考えています。

※予測月は予測している月
※対象銘柄数は予測を行った銘柄の数
※的中率は、対象銘柄のうち騰落予測があった確率
※判定不能銘柄数は、予測月に上昇も下落もしなかった銘柄
※予測上昇銘柄数は、上昇すると予測した銘柄の数
※予測下落銘柄数は、下落すると予測した銘柄の数
※実際上昇銘柄数は、実際に上昇した銘柄の数
※実際下落銘柄数は、実際に下落した銘柄の数
※上昇銘柄的中率は、上昇を予測し、実際に上昇した銘柄の確率
※下落銘柄的中率は、下落を予測し、実際に下落した銘柄の確率

予測月 12月
対象銘柄数 33銘柄
的中率 69.70%
判定不能銘柄数 0銘柄
予測上昇銘柄数 25銘柄
予測下落銘柄数 8銘柄
実際上昇銘柄数 23銘柄
実際下落銘柄数 10銘柄
上昇銘柄的中率 76%
下落銘柄的中率 50%
予測月 11月
対象銘柄数 59銘柄
的中率 59.32%
判定不能銘柄数 0銘柄
予測上昇銘柄数 47銘柄
予測下落銘柄数 12銘柄
実際上昇銘柄数 43銘柄
実際下落銘柄数 16銘柄
上昇銘柄的中率 70.71%
下落銘柄的中率 16.17%
予測月 10月
対象銘柄数 82銘柄
的中率 72.84%
判定不能銘柄数 1銘柄
予測上昇銘柄数 62銘柄
予測下落銘柄数 20銘柄
実際上昇銘柄数 60銘柄
実際下落銘柄数 21銘柄
上昇銘柄的中率 80.65%
下落銘柄的中率 45.00%
予測月 9月
対象銘柄数 64銘柄
的中率 61.90%
判定不能銘柄数 1銘柄
予測上昇銘柄数 38銘柄
予測下落銘柄数 26銘柄
実際上昇銘柄数 31銘柄
実際下落銘柄数 32銘柄
上昇銘柄的中率 57.89%
下落銘柄的中率 65.38%
予測月 8月
対象銘柄数 78銘柄
的中率 29.49%
判定不能銘柄数 0銘柄
予測上昇銘柄数 41銘柄
予測下落銘柄数 37銘柄
実際上昇銘柄数 38銘柄
実際下落銘柄数 40銘柄
上昇銘柄的中率 29.27%
下落銘柄的中率 29.23%
予測月 7月
対象銘柄数 89銘柄
的中率 26.97%
判定不能銘柄数 0銘柄
予測上昇銘柄数 25銘柄
予測下落銘柄数 64銘柄
実際上昇銘柄数 70銘柄
実際下落銘柄数 19銘柄
上昇銘柄的中率 60.00%
下落銘柄的中率 14.06%
予測月 6月
対象銘柄数 84銘柄
的中率 67.86%
判定不能銘柄数 0銘柄
予測上昇銘柄数 44銘柄
予測下落銘柄数 40銘柄
実際上昇銘柄数 19銘柄
実際下落銘柄数 65銘柄
上昇銘柄的中率 40.10%
下落銘柄的中率 97.50%
予測月 5月
対象銘柄数 78銘柄
的中率 61.54%
判定不能銘柄数 0銘柄
予測上昇銘柄数 47銘柄
予測下落銘柄数 31銘柄
実際上昇銘柄数 65銘柄
実際下落銘柄数 13銘柄
上昇銘柄的中率 87.24%
下落銘柄的中率 22.58%
予測月 4月
対象銘柄数 70銘柄
的中率 63.77%
判定不能銘柄数 1銘柄
予測上昇銘柄数 57銘柄
予測下落銘柄数 13銘柄
実際上昇銘柄数 43銘柄
実際下落銘柄数 26銘柄
上昇銘柄的中率 64.91%
下落銘柄的中率 53.85%
予測月 3月
対象銘柄数 60銘柄
的中率 36.67%
判定不能銘柄数 0銘柄
予測上昇銘柄数 18銘柄
予測下落銘柄数 42銘柄
実際上昇銘柄数 46銘柄
実際下落銘柄数 14銘柄
上昇銘柄的中率 72.22%
下落銘柄的中率 21.43%
予測月 2月
対象銘柄数 56銘柄
的中率 78.57%
判定不能銘柄数 0銘柄
予測上昇銘柄数 6銘柄
予測下落銘柄数 50銘柄
実際上昇銘柄数 10銘柄
実際下落銘柄数 46銘柄
上昇銘柄的中率 33.33%
下落銘柄的中率 84.00%
予測月 1月
対象銘柄数 56銘柄
的中率 55.56%
判定不能銘柄数 2銘柄
予測上昇銘柄数 30銘柄
予測下落銘柄数 26銘柄
実際上昇銘柄数 8銘柄
実際下落銘柄数 46銘柄
上昇銘柄的中率 20.00%
下落銘柄的中率 92.30%

売買シミュレーションを行ってみた

単純にその月の始値とその月の終値で売買シミュレーションを行ったところ、予測精度と対して変わらない結果が出たので、それじゃあ面白くないので、実際の売買に近づけたシミュレーションを行いました。

上昇を予測している銘柄は100株買い、下落を予測している銘柄は100株売りのポジションから入ります。

その月の始めの始値で買い、ATRトレーリングストップで損切りラインを決め、損切りラインを超えればその日の終値で売ります。

もし、損切りラインを割ることがなければその月の末の終値で売ります。

手数料は、1回の売買で200円に固定して計算しています。

ATRは4倍で計算しています。


ATRトレーリングストップとは、トレーリングストップの進化版です。

損切りのラインをそのときの株価の変動に合わせて決めるというものです。

トレーリングストップは、急上昇中or急落中は株価の変動が大きく簡単に損切りラインに達してしまったりすることがあるので、それを回避するために、ATRトレーリングストップでは変動に合わせて損切りラインも下げたりしてトレンドを追っていくという手法です。

詳しい計算方法はググッてね。私はここがわかりやすいかなぁと。

kabu-trading.com

12月 294880円
11月 -503110円
10月 993350円
9月 679520円
8月 -885859円
7月 -1489900円
6月 1120619円
5月 782260円
4月 99460円
3月 -418980円
2月 866991円
1月 -1165650円

最終的には、373,581円の利益でした。

この方法、けっこう落とし穴がありました。

11月と1月は予測精度は50%を超えているにも関わらず、総評価損益はマイナスです。

一体何があったのでしょう!?

詳しく見てみると、ある日を境に損切りが大量に行われていることがわかりました

11月はみなさんの記憶に新しい、大統領選挙です。

前代未聞のしゃがんでからの大ジャンプを日経平均株価が行ったため、しゃがんだ時点で損切りを行っていました。

1月も暴落があったため、同様に多くの銘柄で損切りを行ってます。

こういった予想外を除けば、その月の的中率と比例して利益を出しているようです。

幾度となく暴落暴騰がありましたが、何とか利益で出ていてホッと安心。


月の詳細は以下に掲載します。

予測月 12月
総評価損益 294880円
総評価損益率 101.3%
利益 506330円
損失 -211450円
PF 2.39
予測月 11月
総評価損益 -503110円
総評価損益率 98.87%
利益 726590円
損失 -1229700円
PF 0.59
予測月 10月
総評価損益 993350円
総評価損益率 102.5%
利益 1530530円
損失 -537180円
PF 2.84
予測月 9月
総評価損益 679520円
総評価損益率 113.6%
利益 1290050円
損失 -610530円
PF 2.11
予測月 8月
総評価損益 -885859円
総評価損益率 96.11%
利益 658470円
損失 -1544329円
PF 0.43
予測月 7月
総評価損益 -1489900円
総評価損益率 95.30%
利益 300400円
損失 -1790300円
PF 0.17
予測月 6月
総評価損益 1120619円
総評価損益率 104.02%
利益 2014909円
損失 -894290円
PF 2.25
予測月 5月
総評価損益 782260円
総評価損益率 105.24%
利益 1473750円
損失 -691490円
PF 2.13
予測月 4月
総評価損益 99460円
総評価損益率 100.65%
利益 602990円
損失 -503530円
PF 1.19
予測月 3月
総評価損益 -418980円
総評価損益率 97.26%
利益 399650円
損失 -818630円
PF 0.48
予測月 2月
総評価損益 866991円
総評価損益率 108.70%
利益 1148690円
損失 -281699円
PF 4.07
予測月 1月
総評価損益 -1165650円
総評価損益率 97.84%
利益 328850円
損失 -1494500円
PF 0.22

2016年色々起きすぎてて予測しづらすぎワロタ

けっこうな数の指標を集めてきていますが、それでも予想外はちょくちょく起きています。(おそらく予想外に完全に対応することは不可能)

2016年6月あたりから株を始めているので、過去どのくらいの頻度で暴落暴騰が起きているのかわかりませんが、暴落暴騰ってこんな頻繁に起きるもんかい?!

というかあの著名な投資家ジョージ・ソロスでさえ、大損失を出す年なんで、もう仕方がないですよ、ある程度外れるのは。

普通に考えて、大統領選挙など大きな出来事の前は資金をしまっておくのがグッドなので、そうやって上手く予測結果を使っていくのがベターです。

予測結果に全面的な信頼を置くことはまだまだできません。

機械学習の特徴をしっかりと理解した上で、予測結果は参考すれば大きな助けとなると私は考えています。

2017年1月分の予測結果は、以下のサイトに掲載しています。


https://stockdogi.herokuapp.com/index


主に参考にしたWEBあるいは参考書

主に参考したものだけを掲載します。(基準3回以上訪れたWEBページあるいは参考書)


masamunet.com

masamunet.com

qiita.com

qiita.com

business.nikkeibp.co.jp

イラストで学ぶ 人工知能概論 (KS情報科学専門書)

イラストで学ぶ 人工知能概論 (KS情報科学専門書)

株は技術だ!  倍々で勝ち続ける究極のチャート授業 (相場師朗)

株は技術だ! 倍々で勝ち続ける究極のチャート授業 (相場師朗)

ロボット運用のプロが分析してわかった 最強の株式投資法

ロボット運用のプロが分析してわかった 最強の株式投資法

ビッグ・データで株価を読む

ビッグ・データで株価を読む

1月分の株価予測結果を掲載しました

【目次】

弱くなって戻ってきました

Prediction 〜人工知能による株価の予測〜
https://stockdogi.herokuapp.com/index



予測精度の理論値は、前回より落ちてます。

ただ、その代わりに月始めに予測結果を掲載することができるようになりました。

使い勝手を考えると、基準値を1月10日に設けて株価を予測するよりかは、月始めに月末の株価予測を掲載したほうがシンプルでいいかなぁと。

もう1月4日(月始め)過ぎてしまったので、2月の月始めには間に合わせようと思います。

弱くなった原因

説明変数をいじったからです。

集計に時間がかかる系のデータは全て除きました。

つまり、12月分のデータが1月に発表されるものは除いています。

なので、米雇用統計なんかはいれていません。(けっこうな痛手)


米雇用統計以外にも切り離したくないデータを断腸の思いで除きました。

するとガタッと予測精度が落ちました。

なので、新たにデータを探して追加するなどして、前回より予測精度ちょい落ちくらいに落ち着きました。

問題点

安定性落ちたかも。

前までは、幅広くデータを集めてきていたので、ある程度の数の事象をカバーできていたので比較的予測精度が安定していました。

しかし、今回月始めに掲載することにこだわったため、月内にデータが集まるものに絞りました。

それゆえ、説明変数に少し偏りがでてしまいました。

実用には程遠いが株選びの参考にはなる

株価予測結果に従って取引できる日はまだ遠い...

なんせ安定しません。

大きく利益が出るときもあれば、その逆もしかりという状態です。

近いうちに、予測精度の当たり外れのシミュレーションだけでなく、予測結果に従った運用シミュレーションもサイトのコンテンツに追加する予定です。


シストレにおいて、ストラテジーの安定性はとても重要です。

もし、このシステムの従う通りに株の売買をすると、損益グラフの上下運動激しくて、ドキドキハラハラが止まらない経験ができると思います。

現時点では、参考程度にとどめておくのがベストです。


ただ、掲載している予測精度に間違いはありません。

実際にこのシステムで12月の株価を予測した結果は、予測精度54%です。

シミュレーション結果もそこそこかなぁと。

参考程度にとどめておく必要がありますが、参考にはなるということです。

まだまだ改善の余地はある

これが救いであり、かつ苦しいところです。

もう11月頃からずーーーーーーーーーーーーーーっとやっているので、そろそろ疲れが...

4月から社会人なので、今のゴミのような生活リズムも正す必要が...


ただ、追加してみたいデータありますし、工夫してみたいコードもあります。

もう少し頑張ってみます。

Prediction 〜人工知能による株価の予測〜
https://stockdogi.herokuapp.com/index


ブラウザに閉じる前にぜひクリックしましょう!笑


続く!

1月の株価予測を1月頭に出すのは無理

月始めに予測を出さればそれがベストだが...

1月の予測を1月1日に出せれば、シンプルでわかりやすいのですが。

さすがにそれは無理っぽいです。

12月のデータ自体揃うのが、1月の早くても初旬あたりだからです。

データによっては、集計に時間かかったりするんでしょうね。

マンション契約率(首都圏)はなかなか説明変数として機能していたんですが、データの発表が次月の中旬頃なんですよね!おそーい!

断腸の思いでマンション契約率は説明変数から外すことにするのですが、中には外せないものもあります。

米国の非農業部門雇用者数は絶対に外せません。

ただ、非農業部門雇用者数の発表は次月の第一金曜日なので、月の頭には間に合いません。

基準日を設けることにしました

月頭に株価予測は出せないので、例えば1月10日に基準日を設けて、基準日から1ヶ月後の株価を予測する形にしたいと思います。

重要なデータは、10日ほど待てばたいていは出揃います。

これが仕様変更ってやつか

SIerで働く人からしたら聞きたくないワードダントツの一位、仕様変更。

これがまさに仕様変更ってやつですね。

2位は404:File Not Foundあたり?

基準日バージョンに変えるために、もう一度コードを見なおさないといけません。

予測精度も変わるはず...

あぁ、本当に面倒くさいです仕様変更。

今春からたくさん聞くことになるであろう仕様変更、早めに慣れておくとします。


1月10日あたりに今月の株価予測を出せればうれしい

あくまでも予定ですが、1月10日頃に今月の株価予測を出したいです。

トラブらなければ...ですが...

Prediction -人工知能による株価の予測- というサービスをリリースしました

Prediction -人工知能による株価の予測-

↓WebサイトURL
https://stockdogi.herokuapp.com/index



どんなサービス?

1ヶ月後の株価を予測し、その結果を掲載しています。

現在、掲載しているのは12月分の予測結果です。

現地点(2016/12/29大引け後)では、全263銘柄中53.44%の予測が的中しています。


予測は、上昇or下落の2択で行っています。

上がり幅、下がり幅は予測していません。

あくまでも1ヶ月後に上昇するのか、あるいは下落するのか、です。

予測方法

Webサイトに訪問していただければ詳しくのっているので、ここでは簡単に。

色々なデータ(株価・経済指標・為替)をだいたい100項目ほど集めてきて、それらのデータの過去4年間を分析しています。

この分析結果から12月の株価を予測しています。

この形で予測し、過去6ヶ月分シミュレーションを行いました。

予測月 予測精度
11月 45.25%
10月 61.30%
9月 54.40%
8月 62.60%
7月 57.47%
6月 54.41%

予測精度は、平均したらだいたい55%くらいあります。

11月の予測精度が悪いのは、おそらく大統領選挙の影響が大きいと思います。

大統領選挙に関するデータは分析していないので完全に「予期せぬ出来事」です。

やはりこういった「予期せぬ出来事」があれば、極端に予測精度が下がるみたいです。

こういった「予期せぬ出来事」が発生しないよう、幅広いデータを使用しているのですが、全てを網羅するのは簡単じゃないですね。

6月にはブレクジットもあったと思いますが、ユーロやポンドなんかが6月末時点で反応していたので、そこらへんをうまく拾えたので予測精度も悪くなっていないのかなぁと思います。

かなりビビってる

HPがBootstrap臭いので、お察しだとは思いますが、本格的なWebサービスを作るのはこれが初めてです。

なので、右も左もわからず至らない点が多いと思います。

もし何かあればご指摘よろしくお願いします。


正直、エラー対処できる自信がなくheroku側でエラーとか落ちたらどうしようとかかなりビビってます。

また、そもそも予測するのに使っているコードのほうにプログラミングミスがあったらどうしよう、とかにもビビりまくってます。

何回も何回も見直しましたが、プログラミングミスって自分じゃあ見つけにくくて、人から指摘されたり、あとから気づいたりすることのほうが多いので。

アクセスそんなになかったら問題ないですが(悲


ただ、アクセスそんなになくても、少なからず見てもらえる人はいるので、URL発行してWebサイトとしてリリースするからにはちゃんとしたいな、という気持ちが大きくて。

多くの困難を乗り越えて...

リリースまでに本当に多くの困難がありました。

11月12月は睡眠時間以外のほとんどがPCとにらめっこっす。

視力たぶん落ちました。

もう本当にやっとの思いって感じです。

今は疲れているので多くは書きませんが...笑


ぜひ、Prediction -人工知能による株価の予測-にアクセスしてみてください。

https://stockdogi.herokuapp.com/index


ご指摘もお待ちしております。

※herokuの無料枠で運用しているので、アクセスに時間がかかるかもしれません。