スポンサーサイト

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

Market Daemon - 株式データ参照機能の実装

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



概要図でいうと、株式データ参照機能(②)の部分のUML図を書いたところまで記事にしました。

次はOmega Chartの株式データにアクセスするためのセッタゲッタを利用して、実際に株式データにアクセスする機能を実装していくことになります。

前回UML図を載せましたが、ここで再度この部分のみ拡大した図を載せます。


ぎりぎり見えますでしょうか?(文字が小さくてすみません。。。)

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

class ArchivedDataAccess extends DataAccess {

    // *********************************************
    // 定数の定義
    // *********************************************
    // プロパティファイルのパス
    private final String propPath = "prop\\ArchivedData.properties";

    // *********************************************
    // インスタンス変数の定義
    // *********************************************
    // データファイルのパス
    private String dataPath;
    // データ
    private byte[] data;
    // データの調査個所(前方検索)
    private int searchForwardPosi;
    // データの調査個所(後方検索)
    private int searchRearPosi;
    // データの保存されている個所(0~7)
    protected int dataPosi;
    // データのバッファリングをONにするか否か
    private boolean dataBuffering;

    // *********************************************
    // インスタンス生成
    // *********************************************
    // 汎用的なI/O処理インスタンス
    private IoControl iocon = new IoControl();

    // *********************************************
    // コンストラクタの定義
    // *********************************************
    ArchivedDataAccess(int code) {
        this.dataPath = iocon.getPropValue(propPath,"data.path");
        this.searchForwardPosi = 0;
        this.searchRearPosi = 0;
        this.dataPosi = 0;
        this.data = archivedDataRead(dataPath,Integer.toString(code));
        this.dataBuffering = false;
    }

    // *********************************************
    // アーカイブ・データを読み込む
    // *********************************************
    private byte[] archivedDataRead(String dataPath,String code) {
        byte[] data = null;
               try{
                   File file = new File(dataPath+code);
                   int length = (int)file.length();
                   data = new byte[length];
                   InputStream in = new FileInputStream(dataPath+code);
                   BufferedInputStream bin = new BufferedInputStream(in);
                   bin.read(data,0,data.length);
            }catch(IOException e){
            }
        return data;
    }

    // *********************************************
    // データポジションの設定
    // *********************************************
    private void setDataPosi(int dataPosi) {
        if ( dataPosi > 0 ) {
            this.dataPosi = dataPosi;
        } else {
            this.dataPosi = 0;
        }
    }

    // *********************************************
    // データのバッファリング設定
    // *********************************************
    protected void setDataBuffering(boolean dataBuffering) {
        this.dataBuffering = dataBuffering;
    }

    // *********************************************
    // 調査ポジションの初期化
    // *********************************************
    private void initSearchPosi() {
        this.searchForwardPosi = 0;
        this.searchRearPosi = 0;
    }

    // *********************************************
    // 日付をX日ずらす
    // *********************************************
    protected void shiftDate(int shiftNum) {
        if ( shiftNum > 0 ) {
            // 32バイト毎に1日のデータが保存されている
            searchForwardPosi += 32*Math.abs(shiftNum);
        } else if ( shiftNum < 0 ) {
            // 32バイト毎に1日のデータが保存されている
            searchForwardPosi -= 32*Math.abs(shiftNum);
        }
    }
    
    // *********************************************
    // 日付をX日ずらす
    // *********************************************
    protected void shiftDays(int shiftNum) {
        if ( shiftNum > 0 ) {
            // 32バイト毎に1日のデータが保存されている
            searchRearPosi -= 32*Math.abs(shiftNum);
        } else if ( shiftNum < 0 ) {
            // 32バイト毎に1日のデータが保存されている
            searchRearPosi += 32*Math.abs(shiftNum);            
        }
    }
    
    // *********************************************
    // 日付を取得する
    // *********************************************
    protected int[] getDateValue() {
        // 期間を取得
        int period = getPeriod();
        // 戻り値
        int returnValue[] = new int[Math.abs(period)];
        // データポジションセット
        setDataPosi(0);
        // データ取得
        returnValue = getValue();
        // 戻り値リターン
        return returnValue;
    }

    // *********************************************
    // 始値を取得する
    // *********************************************
    protected int[] getStartValue() {
        // 期間を取得
        int period = getPeriod();
        // 戻り値
        int returnValue[] = new int[Math.abs(period)];
        // データポジションセット
        setDataPosi(1);
        // データ取得
        returnValue = getValue();
        // 戻り値リターン
        return returnValue;
    }

    // *********************************************
    // 高値を取得する
    // *********************************************
    protected int[] getHighValue() {
        // 期間を取得
        int period = getPeriod();
        // 戻り値
        int returnValue[] = new int[Math.abs(period)];
        // データポジションセット
        setDataPosi(2);
        // データ取得
        returnValue = getValue();
        // 戻り値リターン
        return returnValue;
    }

    // *********************************************
    // 安値を取得する
    // *********************************************
    protected int[] getLowValue() {
        // 期間を取得
        int period = getPeriod();
        // 戻り値
        int returnValue[] = new int[Math.abs(period)];
        // データポジションセット
        setDataPosi(3);
        // データ取得
        returnValue = getValue();
        // 戻り値リターン
        return returnValue;
    }

    // *********************************************
    // 終値を取得する
    // *********************************************
    protected int[] getEndValue() {
        // 期間を取得
        int period = getPeriod();
        // 戻り値
        int returnValue[] = new int[Math.abs(period)];
        // データポジションセット
        setDataPosi(4);
        // データ取得
        returnValue = getValue();
        // 戻り値リターン
        return returnValue;
    }

    // *********************************************
    // 出来高を取得する
    // *********************************************
    protected int[] getVolume() {
        // 期間を取得
        int period = getPeriod();
        // 戻り値
        int returnValue[] = new int[Math.abs(period)];
        // データポジションセット
        setDataPosi(5);
        // データ取得
        returnValue = getValue();
        // 戻り値リターン
        return returnValue;
    }

    // *********************************************
    // 信用買残を取得する
    // *********************************************
    protected int[] getTrustedBuyAmount() {
        // 期間を取得
        int period = getPeriod();
        // 戻り値
        int returnValue[] = new int[Math.abs(period)];
        // データポジションセット
        setDataPosi(6);
        // データ取得
        returnValue = getValue();
        // 戻り値リターン
        return returnValue;
    }

    // *********************************************
    // 信用売残を取得する
    // *********************************************
    protected int[] getTrustedSaleAmount() {
        // 期間を取得
        int period = getPeriod();
        // 戻り値
        int returnValue[] = new int[Math.abs(period)];
        // データポジションセット
        setDataPosi(7);
        // データ取得
        returnValue = getValue();
        // 戻り値リターン
        return returnValue;
    }

    // *********************************************
    // int[]型のデータを取得する
    // *********************************************
    private int[] getValue() {
        // X営業日前指定を取得
        int daysAgo = getDaysAgo();
        // 日付を取得
        int date = getDate();
        // 期間を取得
        int period = getPeriod();
        // 戻り値
        int returnValue[] = new int[Math.abs(period)];
        // データのバッファリング可否をチェックする
        if ( ! dataBuffering ) {
            // バッファリングしない場合、各ポジションをリセットする
            // (擬似的にバッファリングをオフにする)
            initSearchPosi();
        }
        // dateが指定されている場合(前方検索)
        if ( date > 0 ) {
            // date日のデータを取得
            while ( searchForwardPosi < data.length ) {
                if ( getValue(data.length-searchForwardPosi) == date ) {
                    // Xレコード目にポジションを移動
                    searchForwardPosi += 4*dataPosi;
                    returnValue[0] = getValue(data.length-searchForwardPosi);
                    break;
                }
                // 日付を1日進める
                shiftDate(1);
            }
            // date日以前のデータを取得
            for ( int i = 1; i < Math.abs(period); i++ ) {
                // 日付を1日戻す
                shiftDate(-1);
                returnValue[i] = getValue(data.length-searchForwardPosi);
            }
        // daysAgoが指定されている場合(後方検索)
        } else if ( daysAgo > 0 ) {
            // daysAgo分戻る
            shiftDays(-daysAgo);
            // データ取得
            for ( int i = 0; i < Math.abs(period); i++ ) {
                // Xレコード目にポジションを移動して値を取得
                returnValue[i] = getValue(searchRearPosi-4*dataPosi);
                // 日付を1日戻す
                shiftDays(-1);
            }
        }
        // 戻り値リターン
        return returnValue;
    }

    // *********************************************
    // データ取得メソッド
    // *********************************************
    private int getValue(int searchPosi) {
        // 戻り値
        int returnValue = -1;
        // データ取得
        returnValue = Utility.readUnsignedInt(data,data.length-searchPosi);
        // 戻り値リターン
        return returnValue;
    }
}

各種インポートは良いとして、まずプロパティ・ファイルに何を書いているかですが、以下のような感じでOmega Chartのデータファイルが格納されているパスを記述しています。

data.path=D:\\Omega Chart\\data\\

次に特筆すべきところは、データファイルに対してアクセスする方向を前方検索、後方検索の2パターン用意しているところです。

これは、ある日付のデータを探す場合は前方検索、最新のデータからX日前までを取得するといった場合には後方検索をする必要があるからです。

過去の記事でも書きましたが、Omega Chartのデータファイルは32バイトが1日分のデータとなっていて、その中に4バイトずつ日付や始値などが記録されています。

従って、まずは32バイトごとに調査するバイトをシフトしていき、対象となる日付を探すわけです。

その上で、データの保存されている個所(0~7)までバイトをシフトすれば、お目当てのデータが見つかるというわけです。

肝心かなめのデータ取得メソッドでは、これも過去の記事で作成したUtility.readUnsignedIntメソッドを使用して、指定されたバイトデータの、指定されたバイトポジションのデータをリターンするように作っています。

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

スポンサーサイト

コメント

コメントの投稿


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

トラックバック

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