kivantium活動日記

プログラムを使っていろいろやります

絶対に働きたくない

僕の人生の目標の一つは人類が労働しないで済む世の中を実現することになのですが、現在の世界は残念ながら労働しないと金が入らない仕組みになっているようです。金がないと何をやるにも困るのでなんとかして働かずに金を手にいれたいと思います。労せずに金を得る手段として有力なものの一つが投資です。機械学習で投資対象の予測を行って儲けることができれば、人工知能が人類(僕)を労働から解放したと言ってもよいでしょう!
というわけで機械学習で市場の予測を行いたいと思います。

投資対象の選定

投資をやると決めたからには儲かりそうなものに投資する必要があります。主な投資対象としては株式などの債権、FXなどの外国為替国債、不動産などがありますが、短期間で価格変動があり、かつ有り金を全部溶かさない程度のリスクで収まる対象として、とりあえず株式を選択しました。

株式といってもいろいろな銘柄があるわけですが、会社ごとに投資すると企業の研究などの労働が必要になって面倒くさいので日経平均のような市場の平均に対して投資を行いたいと思います。都合の良いことにETFと呼ばれる指標に連動して価格が変動する証券には2万円以下の少額で購入できるものがいくつもあるので大変よさそうです。というわけで投資対象として、1365ダイワ 上場投信-日経平均レバレッジ(価格変動率が日経平均の変動率のおよそ2倍になるETF)と1366ダイワ上場投信-日経平均ダブルインバース・インデックス(価格変動率が日経平均の変動率のおよそ-2倍になるETF)を選びました。日経平均が上がると予想したら1365を、下がると予想したら1366を買えばいいのでお手軽です。

株式を買うには証券会社と契約しないといけないのですが、今回は松井証券を選びました。一日10万円以下の取引なら手数料がかからないことがポイントでした。

ところで、この前読んだ「ゆずりはコーポレーション」という4コママンガは、社長令嬢・ゆずりはが父親から渡された一千万円を一億円に増やそうと奮闘する話で大変良かったです。

というわけでゆずりはちゃんに負けないよう、僕も振り込んだ10万円を10倍に増やすことをとりあえず目標にしようと思います。

投資方法を考える

株取引の本をいくつか読んでみてどうやらチャートを眺めれば法則性が見えるとのことだったのでしばらくは人の目で予想して買っていたのですが、全然儲かりません。これはダメなので機械学習に任せようと思います。

RVM

過去の株価から明日の株価を求めるような機械学習の手法は回帰と呼ばれます。回帰の手法にはいくつかあるのですが、RVMという方法が良さげだったのでそれを採用しました。
RVMの適当な実装があればそれを使うところなのですが、どうやらRVMはアメリカでMicrosoftが特許を取っているらしいので実装しているライブラリがないようです。PRMLには式が書いてあるのでそれを見ながら実装します。Python実装がRVMで回帰 - きちめもにあったので一部参考にしました。重い処理らしいのでC++で書きました。

以前テレビで見た株価予想プログラムが直前の5日間の値を見ていたので、ここでは直前5日間の日経平均終値を入力として翌日の日経平均終値を予想するモデルにしました。データは日経の指数 - 日経平均プロフィルCSVを加工しました。

#include <iostream>
#include <vector>
#include <cmath>
#include <Eigen/Dense>

using namespace std;
using namespace Eigen;

double kernel(VectorXd x1, VectorXd x2, double sigma = 1.0){
    return exp(-(x1-x2).squaredNorm()/1.0);
}

int main(){
    int N;
    vector<VectorXd> data;
    cin >> N;
    VectorXd t(N);
    for(int i=0; i<N; ++i){
        cin >> t(i);
        VectorXd tmp(5);
        for(int j=0; j<5; ++j){
            cin >> tmp(j);
        }
        data.push_back(tmp);
    }
    int M = N+1;
    VectorXd alpha(M);
    for(int i=0; i<M; ++i) alpha(i) = 1.0;
    double beta = 1.0;
    MatrixXd Phi(N, M);
    for(int n=0; n<N; ++n){
        for(int i=0; i<N; ++i){
            Phi(n, i) = kernel(data[n], data[i]);
        }
        Phi(n, M-1) = 1;
    }

    MatrixXd A, Sigma;
    VectorXd m;
    for(int loop=0; loop<100; loop++){
        A = alpha.asDiagonal();
        Sigma = (A + beta*Phi.transpose()*Phi).inverse();
        m = beta*Sigma*Phi.transpose()*t;
        VectorXd gamma(M);
        for(int i=0; i<M; ++i){
            gamma(i) = 1 - alpha(i)*Sigma(i, i);
        }
        for(int i=0; i<M; ++i){
            double tmp = gamma(i)/(m(i)*m(i));
            if(tmp >= 1e10) alpha(i) = 1e10;
            else alpha(i) = tmp;
        }

        double gamma_sum = 0;
        for(int i=0; i<M; ++i){
            gamma_sum += gamma(i);
        }
        beta = (N-gamma_sum) / (t-Phi*m).squaredNorm();
    }
    cout << m.size() << endl;
    VectorXd test(5);
    test(0) = 18155.71;
    test(1) = 18418.64;
    test(2) = 17758.13;
    test(3) = 17941.91;
    test(4) = 17674.82;
    double result = 0;
    for(int i=0; i<N; ++i){
        result += m(i)*kernel(test, data[i]);
    }
    result += m(N);
    cout << result << endl;
}

入力がベタ書きであることからも分かるように適当な実装です。

結果

過去500, 400, 300, 200, 100, 50日のデータを入力とした時の明日の日経平均終値の予想は15381.5, 15366.4, 17715.5, 19649, 20307.5, 20477.6円でした。金曜日の終値が18264.22円なのでデータによって上がるのか下がるのかすら変わってしまうというひどい予想です。何となくデータ集計期間の平均値がすごく効いている気がします。さすがに日経平均のような適当に揺れ動くもののモデルを綺麗に立てるのは難しいのでしょうか……。直近のデータを使った予想が全部上がると言っているのでとりあえず明日は上がると予想することにしておきます。

RVMがうまくいかなさそうな感じなので次回以降はニューラルネットワークなどのより複雑な手法を採用してみようと思います。
人工知能が労働から解放してくれる未来を目指して……!