スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Market Daemon - テクニカルデータ参照機能の実装

前回の記事の続きです。(クリックすると拡大されます。拡大した図で文字が見づらい方は、画像を100%のサイズで表示してみてください。)



随分と期間があいてしまったので、何をやっていたのかすっかり忘れてしまいそうなのですが(汗)、概要図でいうと、株式データ参照機能(②)を作りこんでいるところですね。

今回はテクニカルデータにアクセスするためのプログラムを作成していきます。
(UML図はこんな感じになります。)



テクニカルデータというと、それこそさまざまなものがあるのですが、今回は移動平均、移動平均乖離率、RSI、ストキャスティクス(Fast/Slow)あたりを実装しようと思います。

先ほどのUML図を元に実際にコーディングしていくとこんな感じになります。
(ちょっと長いですが・・・)
// *********************************************
// プログラム名:TechnicalDataAccess.java
// プログラム概要:テクニカル・データにアクセスする
// *********************************************
// パッケージ:mdp.data
// *********************************************
package mdp.data;
// *********************************************
// 各種インポート
// *********************************************
import util.Utility;

class TechnicalDataAccess extends DataAccess {

    // *********************************************
    // インスタンス変数の定義
    // *********************************************
    // 証券コード
    private int code;
    // 平均値の算出期間
    private int daysOfAverage;
    // RSIの算出期間
    private int daysOfRSI;
    // ファーストストキャスティクス%Kの算出期間
    private int daysOfFastStochasticsK;
    // ファーストストキャスティクス%Dの算出期間
    private int daysOfFastStochasticsD;
    // スローストキャスティクスSDの算出期間
    private int daysOfSlowStochasticsSD;
    // アーカイブ・データ・アクセス処理型オブジェクト
    private ArchivedDataAccess ada;
    
    // *********************************************
    // コンストラクタの定義
    // *********************************************
    TechnicalDataAccess(int code) {
        this.code = code;
        this.daysOfAverage = 14;
        this.daysOfRSI = 14;
        this.daysOfFastStochasticsK = 9;
        this.daysOfFastStochasticsD = 3;
        this.daysOfSlowStochasticsSD = 3;
    }
    
    // *********************************************
    // アーカイブ・データ・アクセス処理インスタンスを初期化する
    // *********************************************
    private void initArchivedDataAccess(int period) {
        // 日付を取得
        int date = getDate();
        // X営業日前を取得
        int daysAgo = getDaysAgo();
        // アーカイブ・データ・アクセス処理インスタンス生成
        ada = new ArchivedDataAccess(code);
        // 日付とX営業日前の設定
        if ( date > 0 ) {
            ada.setDate(date);
        } else if ( daysAgo > 0 ) {
            ada.setDaysAgo(daysAgo);
        }
        // 期間の設定
        ada.setPeriod(period);
    }
    
    // *********************************************
    // 前日比を取得する
    // *********************************************
    protected int[] getCompDayBefore() {
        // 期間を取得
        int period = Math.abs(getPeriod());
        // 一時的な終値保存変数を初期化
        // ※設定されている期間より1日多くデータを取得する
        int[] tmpEndValue = new int[period+1];
        for (int i = 0; i < period+1; i++) {
            tmpEndValue[i] = -1;
        }
        // アーカイブ・データ・アクセス処理インスタンスを初期化
        // ※設定されている期間より1日多くデータを取得する
        initArchivedDataAccess(period+1);
        // 前日比初期化
        int[] compDayBefore = new int[period];
        for (int i = 0; i < period; i++) {
            compDayBefore[i] = 0;
        }
        // 終値取得
        tmpEndValue = ada.getEndValue();
        // 前日比取得
        for (int i = 0; i < period; i++) {
            compDayBefore[i] = tmpEndValue[i] - tmpEndValue[i+1];
        }
        // 戻り値リターン
        return compDayBefore;
    }
    
    // *********************************************
    // 平均値の算出期間をセットする
    // *********************************************
    protected void setDaysOfAverage(int daysOfAverage) {
        // 平均値の算出期間をセット
        this.daysOfAverage = daysOfAverage;
    }
    
    // *********************************************
    // 平均値の算出期間を取得する
    // *********************************************
    protected int getDaysOfAverage() {
        // 平均値の算出期間をセット
        return daysOfAverage;
    }
    
    // *********************************************
    // RSIの算出期間をセットする
    // *********************************************
    protected void setDaysOfRSI(int daysOfRSI) {
        // 平均値の算出期間をセット
        this.daysOfRSI = daysOfRSI;
    }
    
    // *********************************************
    // RSIの算出期間を取得する
    // *********************************************
    protected int getDaysOfRSI() {
        // 平均値の算出期間をセット
        return daysOfRSI;
    }
    
    // *********************************************
    // ファーストストキャスティクス%Kの算出期間をセットする
    // *********************************************
    protected void setDaysOfFastStochasticsK(int daysOfFastStochasticsK) {
        // 平均値の算出期間をセット
        this.daysOfFastStochasticsK = daysOfFastStochasticsK;
    }
    
    // *********************************************
    // ファーストストキャスティクス%Kの算出期間を取得する
    // *********************************************
    protected int getDaysOfFastStochasticsK() {
        // 平均値の算出期間をセット
        return daysOfFastStochasticsK;
    }
    
    // *********************************************
    // ファーストストキャスティクス%Dの算出期間をセットする
    // *********************************************
    protected void setDaysOfFastStochasticsD(int daysOfFastStochasticsD) {
        // 平均値の算出期間をセット
        this.daysOfFastStochasticsD = daysOfFastStochasticsD;
    }
    
    // *********************************************
    // ファーストストキャスティクス%Dの算出期間を取得する
    // *********************************************
    protected int getDaysOfFastStochasticsD() {
        // 平均値の算出期間をセット
        return daysOfFastStochasticsD;
    }
    
    // *********************************************
    // スローストキャスティクスSDの算出期間をセットする
    // *********************************************
    protected void setDaysOfSlowStochasticsSD(int daysOfSlowStochasticsSD) {
        // 平均値の算出期間をセット
        this.daysOfSlowStochasticsSD = daysOfSlowStochasticsSD;
    }
    
    // *********************************************
    // スローストキャスティクスSDの算出期間を取得する
    // *********************************************
    protected int getDaysOfSlowStochasticsSD() {
        // 平均値の算出期間をセット
        return daysOfSlowStochasticsSD;
    }
    
    // *********************************************
    // 値下がり幅を取得する
    // *********************************************
    protected int getDownValue() {
        // 期間を取得
        int period = Math.abs(getPeriod());
        // 値上がり幅を初期化
        int downValue = 0;
        // 前日比取得
        int[] compDayBefore = getCompDayBefore();
        // 値上がり幅を取得
        for (int i = 0; i < period; i++) {
            if (compDayBefore[i] < 0) {
                downValue += compDayBefore[i];
            }
        }
        // 戻り値リターン
        return downValue;
    }
    
    // *********************************************
    // 値上がり幅を取得する
    // *********************************************
    protected int getUpValue() {
        // 期間を取得
        int period = Math.abs(getPeriod());
        // 値上がり幅を初期化
        int upValue = 0;
        // 前日比取得
        int[] compDayBefore = getCompDayBefore();
        // 値上がり幅を取得
        for (int i = 0; i < period; i++) {
            if (compDayBefore[i] > 0) {
                upValue += compDayBefore[i];
            }
        }
        // 戻り値リターン
        return upValue;
    }
    
    // *********************************************
    // 平均値を取得する
    // *********************************************
    protected double[] getAverage() {
        // 日付を取得
        int date = getDate();
        // X営業日前を取得
        int daysAgo = getDaysAgo();
        // アーカイブ・データ・アクセス処理インスタンスを初期化
        // ※daysOfAverage間のデータを取得する
        initArchivedDataAccess(getDaysOfAverage());
        // 期間を取得
        int period = Math.abs(getPeriod());
        // 平均値を初期化
        double[] average = new double[period];
        for (int i = 0; i < period; i++) {
            average[i] = -1.0;
        }
        // daysAgoが設定されている場合
        if ( daysAgo > 0 ) {
            for ( int i = 0; i < period; i++ ) {
                // 平均値を取得
                average[i] = Utility.getAverage(ada.getEndValue());
                // daysAgoを1日増やす
                ada.setDaysAgo(ada.getDaysAgo()+1);
            }
        // dateが設定されている場合
        } else if ( date > 0 ) {
            // 日付配列保管用一時変数を設定
            int[] tmpDate = new int[period];
            tmpDate = ada.getDateValue();
            for ( int i = 0; i < period; i++ ) {
                // 日付を設定
                ada.setDate(tmpDate[i]);
                // 平均値を取得
                average[i] = Utility.getAverage(ada.getEndValue());
            }
        }
        // 戻り値リターン
        return average;
    }
    
    // *********************************************
    // 平均乖離率を取得
    // *********************************************
    protected double[] getDistFromAverage() {
        // アーカイブ・データ・アクセス処理インスタンスを初期化
        // ※daysOfAverage間のデータを取得する
        initArchivedDataAccess(getDaysOfAverage());
        // 期間を取得
        int period = Math.abs(getPeriod());
        // 終値を取得
        int[] endValue = ada.getEndValue();
        // 平均乖離率を初期化
        double[] distFromAverage = new double[period];
        for ( int i = 0; i < period; i++ ) {
            distFromAverage[i] = 0.0;
        }
        // 平均値を取得
        double[] average = getAverage();
        // 平均乖離率を取得
        for ( int i = 0; i < period; i++ ) {
            distFromAverage[i] = (((double)endValue[i]-average[i])/average[i])*100.0;
        }
        // 戻り値リターン
        return distFromAverage;
    }
    
    // *********************************************
    // RSIを取得
    // *********************************************
    protected double[] getRSI() {
        // 日付を取得
        int date = getDate();
        // X営業日前を取得
        int daysAgo = getDaysAgo();
        // 期間を取得
        int period = Math.abs(getPeriod());
        // 期間のバックアップ
        int backupPeriod = period;
        // RSI算出期間
        int daysOfRSI = getDaysOfRSI();
        // 値上がり幅の合計を初期化
        int[] upValue = new int[period];
        for ( int i = 0; i < period; i++ ) {
            upValue[i] = 0;
        }
        // 値下がり幅の合計を初期化
        int[] downValue = new int[period];
        for ( int i = 0; i < period; i++ ) {
            downValue[i] = 0;
        }
        // RSIを初期化
        double[] rsi = new double[period];
        for ( int i = 0; i < period; i++ ) {
            rsi[i] = -1.0;
        }
        // アーカイブ・データ・アクセス処理インスタンスを初期化
        // ※daysOfRSI間のデータを取得する
        initArchivedDataAccess(daysOfRSI);
        // daysAgoが設定されている場合
        if ( daysAgo > 0 ) {
            for ( int i = 0; i < period; i++ ) {
                // 期間をRSI取得期間に設定する
                setPeriod(daysOfRSI);
                // 値上がり幅の合計を取得
                upValue[i] = getUpValue();
                // 値下がり幅の合計を取得
                downValue[i] = getDownValue();
                // 期間を元に戻す
                setPeriod(backupPeriod);
                // daysAgoを1日増やす
                setDaysAgo(getDaysAgo()+1);
            }
            // dateが設定されている場合
        } else if ( date > 0 ) {
            // 日付配列保管用一時変数を設定
            int[] tmpDate = new int[period];
            tmpDate = ada.getDateValue();
            for ( int i = 0; i < period; i++ ) {
                // 日付を設定
                setDate(tmpDate[i]);
                // 期間をRSI取得期間に設定する
                setPeriod(daysOfRSI);
                // 値上がり幅の合計を取得
                upValue[i] = getUpValue();
                // 値下がり幅の合計を取得
                downValue[i] = getDownValue();
                // 期間を元に戻す
                setPeriod(backupPeriod);
            }
        }
        // RSIを取得
        for ( int i = 0; i < period; i++ ) {
            rsi[i] = ((double)upValue[i]/(double)(upValue[i]+Math.abs(downValue[i])))*100;
        }
        // 戻り値リターン
        return rsi;
    }
    
    // *********************************************
    // ファーストストキャスティクス%Kを取得
    // *********************************************
    protected double[] getFastStochasticsK() {
        // 日付を取得
        int date = getDate();
        // X営業日前を取得
        int daysAgo = getDaysAgo();
        // 期間を取得
        int period = Math.abs(getPeriod());
        // アーカイブ・データ・アクセス処理インスタンスを初期化
        initArchivedDataAccess(period);
        // 終値を取得
        int[] endValue = ada.getEndValue();
        // 安値を初期化
        int[] lowValue = new int[period];
        for ( int i = 0; i < period; i++ ) {
            lowValue[i] = -1;
        }
        // 高値を初期化
        int[] highValue = new int[period];
        for ( int i = 0; i < period; i++ ) {
            highValue[i] = -1;
        }
        // ファーストストキャスティクス%Kを初期化
        double[] fastStochasticsK = new double[period];
        for ( int i = 0; i < period; i++ ) {
            fastStochasticsK[i] = -1.0;
        }
        // アーカイブ・データ・アクセス処理インスタンスを初期化
        // ※daysOfFastStochasticsK間のデータを取得する
        initArchivedDataAccess(getDaysOfFastStochasticsK());
        // daysAgoが設定されている場合
        if ( daysAgo > 0 ) {
            for ( int i = 0; i < period; i++ ) {
                // 安値を取得
                lowValue[i] = Utility.getMin(ada.getLowValue());
                // 高値を取得
                highValue[i] = Utility.getMax(ada.getHighValue());
                // daysAgoを1日増やす
                ada.setDaysAgo(ada.getDaysAgo()+1);
            }
        // dateが設定されている場合
        } else if ( date > 0 ) {
            // 日付配列保管用一時変数を設定
            int[] tmpDate = new int[period];
            tmpDate = ada.getDateValue();
            for ( int i = 0; i < period; i++ ) {
                // 日付を設定
                ada.setDate(tmpDate[i]);
                // 安値を取得
                lowValue[i] = Utility.getMin(ada.getLowValue());
                // 高値を取得
                highValue[i] = Utility.getMax(ada.getHighValue());
            }
        }
        // ファーストストキャスティクス%Kを取得
        for ( int i = 0; i < period; i++ ) {
            fastStochasticsK[i] = ((double)endValue[i]-(double)lowValue[i])/((double)highValue[i]-(double)lowValue[i])*100.0;
        }
        // 戻り値リターン
        return fastStochasticsK;
    }
    
    // *********************************************
    // ファーストストキャスティクス%Dを取得
    // *********************************************
    protected double[] getFastStochasticsD() {
        // 日付を取得
        int date = getDate();
        // X営業日前を取得
        int daysAgo = getDaysAgo();
        // 期間を取得
        int period = Math.abs(getPeriod());
        // period期間にdaysOfFastStochasticsD期間を加算して1引いた期間を取得
        int collectPeriod = period+getDaysOfFastStochasticsD()-1;
        // 分母を初期化
        int[] molecule = new int[period];
        for ( int i = 0; i < period; i++ ) {
            molecule[i] = 0;
        }
        // 分子を初期化
        int[] denominator = new int[period];
        for ( int i = 0; i < period; i++ ) {
            denominator[i] = 0;
        }
        // 安値を初期化
        int[] lowValue = new int[collectPeriod];
        for ( int i = 0; i < collectPeriod; i++ ) {
            lowValue[i] = -1;
        }
        // 高値を初期化
        int[] highValue = new int[collectPeriod];
        for ( int i = 0; i < collectPeriod; i++ ) {
            highValue[i] = -1;
        }
        // 終値を初期化
        int[] endValue = new int[collectPeriod];
        for ( int i = 0; i < collectPeriod; i++) {
            endValue[i] = -1;
        }
        // ファーストストキャスティクス%Dを初期化
        double[] fastStochasticsD = new double[period];
        for ( int i = 0; i < period; i++ ) {
            fastStochasticsD[i] = -1.0;
        }
        // アーカイブ・データ・アクセス処理インスタンスを初期化
        initArchivedDataAccess(collectPeriod);
        // 終値を取得
        endValue = ada.getEndValue();
        // アーカイブ・データ・アクセス処理インスタンスを初期化
        // ※daysOfFastStochasticsK間のデータを取得する
        initArchivedDataAccess(getDaysOfFastStochasticsK());
        // daysAgoが設定されている場合
        if ( daysAgo > 0 ) {
            for ( int i = 0; i < collectPeriod; i++ ) {
                // 安値を取得
                lowValue[i] = Utility.getMin(ada.getLowValue());
                // 高値を取得
                highValue[i] = Utility.getMax(ada.getHighValue());
                // daysAgoを1日増やす
                ada.setDaysAgo(ada.getDaysAgo()+1);
            }
        // dateが設定されている場合
        } else if ( date > 0 ) {
            // 日付配列保管用一時変数を設定
            int[] tmpDate = new int[collectPeriod];
            tmpDate = ada.getDateValue();
            for ( int i = 0; i < collectPeriod; i++ ) {
                // 日付を設定
                ada.setDate(tmpDate[i]);
                // 安値を取得
                lowValue[i] = Utility.getMin(ada.getLowValue());
                // 高値を取得
                highValue[i] = Utility.getMax(ada.getHighValue());
            }
        }
        // 分母と分子を計算
        for ( int i = 0; i < period; i++ ) {
            for ( int j = 0; j < daysOfFastStochasticsD; j++ ) {
                molecule[i] += (endValue[i+j]-lowValue[i+j]);
                denominator[i] += (highValue[i+j]-lowValue[i+j]);
            }
        }
        // ファーストストキャスティクス%Dを取得
        for ( int i = 0; i < period; i++ ) {
            fastStochasticsD[i] = ((double)molecule[i]/(double)denominator[i])*100;
        }
        // 戻り値リターン
        return fastStochasticsD;
    }

    // *********************************************
    // スローストキャスティクスSDを取得
    // *********************************************
    protected double[] getSlowStochasticsSD() {
        // 期間を取得
        int period = Math.abs(getPeriod());
        // 期間のバックアップ
        int backupPeriod = period;
        // daysOfSlowStochasticsSD期間を取得
        int daysOfSlowStochasticsSD = getDaysOfSlowStochasticsSD();
        // period期間にdaysOfSlowStochasticsSD期間を加算して1引いた期間を取得
        int collectPeriod = period+daysOfSlowStochasticsSD-1;
        // 分母を初期化
        double[] molecule = new double[period];
        for ( int i = 0; i < period; i++ ) {
            molecule[i] = 0;
        }
        // 一時的な分母を初期化
        double[] tmpMolecule = new double[collectPeriod];
        for ( int i = 0; i < collectPeriod; i++ ) {
            tmpMolecule[i] = 0;
        }
        // スローストキャスティクスSDを初期化
        double[] slowStochasticsSD = new double[period];
        for ( int i = 0; i < period; i++ ) {
            slowStochasticsSD[i] = -1.0;
        }
        // アーカイブ・データ・アクセス処理インスタンスを初期化
        initArchivedDataAccess(collectPeriod);
        // ファーストストキャスティクス%Dの取得期間を補正
        setPeriod(collectPeriod);
        // 一時的な分母を取得
        tmpMolecule = getFastStochasticsD();
        // 期間を再設定
        setPeriod(backupPeriod);
        // 分母を取得
        for ( int i = 0; i < period; i++ ) {
            for ( int j = 0; j < daysOfSlowStochasticsSD; j++ ) {
                molecule[i] += tmpMolecule[i+j];
            }
        }
        // スローストキャスティクスSDを取得
        for ( int i = 0; i < period; i++ ) {
            slowStochasticsSD[i] = molecule[i]/(double)daysOfSlowStochasticsSD;
        }
        // 戻り値リターン
        return slowStochasticsSD;
    }
}

な…なげえ…(汗)

コンストラクタで各種テクニカルデータの基本取得期間を設定するようにし(例えばRSIであれば14日)、それぞれの値をセット、取得するためのセッタ、ゲッタを用意します。

また、前回作成したアーカイブデータへのアクセス処理インスタンスを生成する際に、日付(YYYYMMDD)指定のデータサーチをするのか、X営業日前といったタイプで指定したデータサーチをするのかを決めておくようにします。

あとは、各テクニカルデータを計算する式を組み込めば完成です。

テクニカルデータの算出式はこちらのサイトなどを参考にすれば、わかりやすいでしょう。

以上の説明では大分はしょっていますが、ここでもそんなに難しいことはやっていない(はず)ですので、ソースコードをざっとおっていただければ、理解できるかと思います。
<<==このブログの応援に、ポチッと押していってください!
スポンサーサイト

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバックURL:
http://atomico.blog72.fc2.com/tb.php/213-75b858dd
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。