プロジェクトSMIS《システムトレード研究開発》

 株価データ取得モジュールA

 それでは次に、取得した株価データをファイルに出力する処理を追加していきましょう。

 とその前に、トレードシステム詳細設計Bの株価データファイル仕様を確認しておきましょう。

 株価データファイル出力処理

 株価データ取得モジュールは毎日定時に起動され、日々の株価を取得していきます。
 ですのでまずは株価データファイルのヘッダ部を作成しておきましょう。

 本来ならばこういうファイルヘッダ作成作業もプログラムで自動的にやるべきです。
 実際のSMISもこういう機能を持ち合わせています。が。。。

 ここではSMISの主要な処理の部分をサンプルソースコードを交えて、出来るだけ完結にご紹介するのが目的ですので、今回は手作業ということでご了承下さい。

 システムの開発が進んで行くとこうした追加したい機能が発生するのは日常茶飯事です。
 エンドユーザの要望をかなえる為にも機能追加したいのはやまやまですが、とりあえず機能追加を保留しておき後で機能追加を検討するのも手ですよね。

 ここではプロジェクトの進行を優先させたいと思います。
 以下の3行の文字列を入力し、「1301.csv」というファイル名で保存します。


1301,(株)極洋,単元株数:1000
 (空白行)
日付,出来高,始値,高値,安値,終値


 では、コーディングに取り掛かりましょう。
 株価データのクラスを作成し、ついでにデータ内容を表示するメソッドおよび株価データファイルを出力するメソッドを追加しておきます。


class SPD {

  String date ;
  String volume ;
  String open ;
  String high ;
  String low ;
  String close ;

  void Display(){
   System.out.println("--------- SPD ----------") ;
   System.out.println("日 付:"+date ) ;
   System.out.println("出来高:"+volume) ;
   System.out.println("始 値:"+open ) ;
   System.out.println("高 値:"+high ) ;
   System.out.println("安 値:"+low ) ;
   System.out.println("終 値:"+close ) ;
   System.out.println("------------------------") ;
  }

  void FileWrite(String code){

   try{

    int i, j ;
    String[] data = new String[1024] ; //データ格納領域

    //既存の株価データファイルを読み込む
    FileInputStream fis = new FileInputStream( code+".csv" );
    InputStreamReader ir = new InputStreamReader(fis , "MS932");
    BufferedReader br = new BufferedReader(ir);

    //読み込み
    for(i=0 ;; i++){
     //System.out.println("i="+i);
     data[i] = br.readLine();

     //ファイル終了みたい
     if(data[i] == null){
      break ;
    }
   }

   //ファイルクローズ
   br.close();
   ir.close();
   fis.close();

   //出力用ファイルのオープン
   FileOutputStream fos = new FileOutputStream( code+".csv");
   OutputStreamWriter osw = new OutputStreamWriter(fos , "MS932");
   BufferedWriter bw = new BufferedWriter(osw);

   for(j=0 ;; j++){

    //更新対象ファイルが256行以上だったら古いデータをとばす(削除)
    if(j == 3 && i >= 256){
     j ++ ;
    }

    //過去のデータ書き込み
    if(data[j] != null){
     bw.write(data[j]) ;
     bw.write("\r\n") ;
    }

    //最新のデータ書き込み
    else{

     String msg = date ;
     bw.write(msg);
     msg = "," ;
     bw.write(msg);

     msg = "\"" ;
     bw.write(msg);
     msg = volume ;
     bw.write(msg);
     msg = "\"," ;
     bw.write(msg);

     msg = "\"" ;
     bw.write(msg);
     msg = open ;
     bw.write(msg);
     msg = "\"," ;
     bw.write(msg);

     msg = "\"" ;
     bw.write(msg);
     msg = high ;
     bw.write(msg);
     msg = "\"," ;
     bw.write(msg);

     msg = "\"" ;
     bw.write(msg);
     msg = low ;
     bw.write(msg);
     msg = "\"," ;
     bw.write(msg);

     msg = "\"" ;
     bw.write(msg);
     msg = close ;
     bw.write(msg);
     msg = "\"\r\n" ;
     bw.write(msg);

     //ファイルクローズ
     bw.close();
     osw.close();
     fos.close();
     break ;
    }
   }
  }
  catch (Exception e) {
   e.printStackTrace();
  }
 }
}


 なんかきちゃないソースで公開するのはとても恥ずかしいのですが・・・
 ま、反面教師ということで「真似しちゃいけない…こんなコーディング」とでもしておきましょう。

 とクラスがそろったところで、メイン処理を変更しましょう。


import java.net.*;
import java.io.*;
import java.util.*;
import java.text.*;

   :
   :

//クラスの定義
Tag tag = new Tag() ;
SPD spd = new SPD() ;

   :
   :

if(line.indexOf("取引値") != -1){
 vol = tag.word(line, 3) ;
 spd.close = vol ;
}
if(line.indexOf("出来高") != -1){
 vol = tag.word(line, 2) ;
 spd.volume = vol ;
}
if(line.indexOf("始値") != -1){
 vol = tag.word(line, 2) ;
 spd.open = vol ;
}
if(line.indexOf("高値") != -1){
 vol = tag.word(line, 2) ;
 spd.high = vol ;
}
if(line.indexOf("安値") != -1){
 vol = tag.word(line, 2) ;
 spd.low = vol ;
}

//日付セット
SimpleDateFormat dateFormat
  = new SimpleDateFormat( "yyyy/MM/dd", Locale.US ) ;
dateFormat.setTimeZone( TimeZone.getDefault() );
spd.date = new String(dateFormat.format( new Date()) );


 実は皆さんも気づいているでしょうが、日付セットのところで現在日時を強引にセットしています。これでは株価の日付とダウンロードした日付がごっちゃになってしまいます。

 株価提供Webサイトの例(http://www5f.biglobe.ne.jp/~uzy/smis/p1301.htm)が悪かったのですが、実際に参照するWebサイト上から日付を持ってくるべきでしょう。

 どうでしょうか?うまく動作しましたか?
 ここでのサンプルコードはエラー処理などが含まれていませんので実際にシステムを運用するためにはいろいろと追加しなければいけないコードがあると思います。

 実際のシステム開発ではあらかじめ想定されるエラー処理は設計段階から仕様としてきちんと挙げておくことが大切です。

 また、プログラムの実行中にエラーが発生した時、どこでどんなエラーが発生したかわかるちょっとした仕掛けを組み込んでおくことで、不具合の原因究明やデバッグが容易くなります。

 こうした工夫は無駄にはならないでしょう。

 株価データ提供サイトはYahoo!をはじめ、Infoseek、MSN等たくさんありますがどこを参照するかは皆さんにお任せします。Webサイトの構成がシンプルでプログラムで参照しやすいところがいいでしょう。

 このプログラムは1つの会社の株価を取得すると終了してしまいます。複数の株価を取得させるにはどうしたらよいでしょうか。

 方法はいくつか考えられますがここではいちばん簡単な方法を示しておきます。
 下記のコードを入力し、「DLoader.bat」というファイル名で保存します。


java DLoader 1301
java DLoader 1331
java DLoader 1332

     :
     :


 あとはこのバッチファイルを実行すれば記述した分だけの株価データを取得することができます。
 Windowsのタスクスケジューラーの機能を利用すれば、月曜〜金曜日、定時に実行させることも可能になります。

 最後に注意をひとつ。

 上記のプログラムを必要以上に何度も実行することは、Webサイトへ頻繁にアクセスすることになり、サーバーの負荷増大を招き、他の皆様へご迷惑をかけることとなります。(場合によってはDoS攻撃とみなされるかも知れません。)

 十分にテストを繰り返してからの使用や、アクセス処理の間にsleep処理を入れる等、配慮することをお忘れなく。。。



株価データ取得モジュール@   プロジェクトSMIS《システムトレード研究開発》   売買判定モジュール@