レベル: 中級 木村 桂 (kimuc@jp.ibm.com), ソフトウェア事業, IBM
2007年 5月 18日 スーパー・カブロボ・コンテストの Java プログラミング上級編の第2回目である今回は、「過去の株価を取得する方法」を紹介します。
カブロボ SDK で用意されているテクニカル手法を利用するだけであれば株価そのものを知る必要はないのですが、実際に株価は上がっているのか下がっているのか、という基本的な情報を得る上で、是非知っておきたい方法だと思っています。またカブロボ SDK で用意されていないテクニカル手法を使いたい場合には、過去の株価をもとに自分で計算する必要がありますから、その場合でもやはり過去の株価を知る方法が必要になります。
「営業日」をさかのぼる
過去の株価を求める上でまず必要になるのが「いつからいつまで」の株価が必要になるか、という情報です。 例えば今日が 2007/05/18 であるとして、「昨日と今日」の株価を知りたいのであれば、「2007/05/17 から 2007/05/18 まで」の株価が必要です。「今日を含めて過去4日間」の株価を知りたいのであれば、「2007/05/15 から 2007/05/18 まで」の株価が必要になる、という意味です。
では「今日を含めて過去 10 日間」の株価を知りたい場合はどうでしょうか?カレンダーを見る限りでは「2007/05/09 から 2007/05/18 まで」の株価が必要になります。でもこの期間中の土曜日(2007/05/12)と日曜日(2007/05/13)は市場が開いていませんから株価は存在していません。実質的に8日分のデータしか取れないことになります。結論として 10 個の株価データを得ようとすると「2007/05/07 から 2007/05/18 まで」のデータが必要になります。 このように、過去の株価を特定個数求める際に「いつからのデータが必要か」という計算には「営業日だけをさかのぼって計算する」という必要があるという点に注意が必要です。
カブロボ SDK では「今日の日付」を求める機能に加えて、そこから「何営業日前の日付」を求めるための機能も装備しています。まず今日(=カブロボが実行をシミュレートしている当日)の日付は TimeManager クラスの getCurrentDate() メソッドを、また特定の営業日だけ前後させるには getBusinessDay() メソッドを利用します(利用例は後述します)。
特定期間内の株価データリストを取得
株価を求める範囲となる日付が確定したら、いよいよ株価を求めます。具体的には InformationManager クラスの getStockDailyByInterval() メソッドに範囲の開始日と終了日を Stock オブジェクトと一緒にパラメータ指定することで、株価データが含まれる StockData クラスのリストが取得できます。
株価を元に売買銘柄を判断するロボット
では実際にロボットを作ってみます。今回作成するロボットの基本戦略は
- 2日続けて株価(終値)が上昇したら買いのサインと見なす
- 2日続けて株価(終値)が下落したら売りのサインと見なす
とします。2日連続して株価が上昇したかどうかを判断するには
- 2営業日前の株価 < 1営業日前の株価 かつ 1営業日前の株価 < 当日の株価 (*)
となっているかどうかを判断すればよいことになりますから、当日も含めて直近3日分の株価情報が必要になります。
前回同様、ロボットそのものは中級編(4)で作成した DwRobot04 をベースに、 DwRobotAdv02 という名前のロボットを以下の内容で作成します:
DwRobotAdv02.java の内容
import java.util.ArrayList;
import java.util.Calendar;
import jp.tradesc.superkaburobo.sdk.driver.RobotDriver;
import jp.tradesc.superkaburobo.sdk.robot.AbstractRobot;
import jp.tradesc.superkaburobo.sdk.trade.TradeAgent;
import jp.tradesc.superkaburobo.sdk.trade.data.Portfolio;
import jp.tradesc.superkaburobo.sdk.trade.data.Stock;
import jp.tradesc.superkaburobo.sdk.trade.data.StockData;
public class DwRobotAdv02 extends AbstractRobot {
@Override
public void order(TradeAgent arg0) {
// TODO Auto-generated method stub
//. 省略(DwRobot04 の order メソッドと同じ)
}
@Override
public void screening(TradeAgent arg0) {
// TODO Auto-generated method stub
//. 当日の日付と2営業日前の日付を取得
Calendar c0 = arg0.getTimeManager().getCurrentDate(); //. 当日 (1)
Calendar c2 = arg0.getTimeManager().getBusinessDay( -3 ); //. 2営業日前 (2)
//. 売買の候補リストを用意
ArrayList<Stock> buyList = new ArrayList<Stock>(); //. 買い候補
ArrayList<Stock> sellList = new ArrayList<Stock>(); //. 売り候補
//. このシミュレーションで取引できる全株銘柄を取得する
ArrayList<Stock> stockList = arg0.getInformationManager().getStockList();
//. 個別に銘柄を1つずつ取得して、直近3日間の株価をチェックする
for( Stock stock : stockList ){
//. この銘柄の、過去3日間(2営業日前から当日まで)の株データリストを取得する (3)
ArrayList<StockData> stockDataList
= arg0.getInformationManager().getStockDailyByInterval( c2, c0, stock );
//. 取得したデータリストから過去3日間の終値を取得する (4)
int cp[] = new int[3];
int i = 0;
for( StockData stockData : stockDataList ){
// cp[0] = 当日の終値、cp[1] = 1営業日前の終値、cp[2] = 2営業日前の終値 (5)
cp[i++] = stockData.getClosingPrice();
}
if( cp[2] < cp[1] cp[1] < cp[0] ){
//. 二日連続で下がった場合は、買い注文の候補としてリストに追加する (6)
buyList.add( stock );
}else if( cp[2] > cp[1] cp[1] > cp[0] ){
//. 二日連続で上がった場合は、売り注文の候補としてリストに追加する (7)
sellList.add( stock );
}
}
//. 買い/売りの候補リストを記憶するメモクラスを用意する
DwMemo memo = new DwMemo();
//. メモに売買それぞれの候補リストを設定する
memo.setBuyList( buyList );
memo.setSellList( sellList );
//. メモを格納する
arg0.getMemoManager().setObjectMemo( memo );
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//. 便利に実行するためのおまじない
String[] arg = { "-n", "DwRobotAdv02" };
RobotDriver.main( arg );
}
}
|
今回も前回同様に order メソッドの内容は DwRobot04 と同じものを利用することにしますので省略します。
一方、screening メソッドでは最初に株価を取得する日付の範囲を決定しています。TimeManager クラスの getCurrentDate() メソッドでまず当日の日付を取得します(1)。そして get BusinessDay() メソッドで当日から指定営業日だけ前後させた日付を取得します。指定営業日だけさかのぼる場合は営業日を負の数で指定しますので、2営業日前の日付は当日も含めると3日前になるので、-3 をパラメータ指定する点に注意してください(2)。
この後、DwRobot04 と同様に売買候補のリスト変数を管理する変数を用意した上で全銘柄を取得し、個別にループさせて売買候補かどうかを判断します。
判断の内容は各銘柄の(当日から2営業日前まで)直近3日分の株価データを取得します。具体的には InformationManager クラスの getStockDailyByInterval メソッドを範囲日付と銘柄クラスをパラメータ指定して実行することで取得できます(3)。プログラム上ではこの結果を stockDataList というリスト変数に格納していますが、このリストには3つの(3日分の)データが含まれることになります。なお、このリストには新しい順にデータが格納される点に注意してください。
株価データのリストを取得したら、ここから終値だけを取り出します(4)。取り出した終値を格納する配列変数として cp を用意し、stockDataList のリストから個別に1つずつデータを取り出しては getClosingPrice() メソッドで終値を取り出して cp に順に格納します(5)。上記で説明したようにデータリストには新しい順にデータが格納されていますから、これによって
cp[0] = 直近の終値(当日の終値)
cp[1] = その1つ前の終値(1営業日前の終値)
cp[2] = 更に1つ前の終値(2営業日前の終値)
が取得できることになります。
なお、今回は終値をデータとして取り出しましたが、もちろん始値、高値、安値といった他の4本値や出来高などの値を取り出すこともできます。詳しくは JavaDoc の StockData クラスのメソッドの内容を参照してください。
3日分の終値データが取得できれば後は比較して売買判断をするだけです。上記説明した (*) の条件を満たしていた場合は2日連続上昇したので買いの候補リストに加えます(6)。また逆に2日連続下落した場合は売りの候補リストに加えます(7)。こうして作成した売買候補リストを元に order メソッドの中で注文・ポジション管理を行うことになります。
こうして作ったロボットを 2004/09/01 から 2005/08/31 まで 50 銘柄でシミュレーション実行した最終結果は以下のようになります。実はこのロジックですと注文頻度がかなり高くなり、途中で取引余力がなくなってしまいます。その意味では不完全なロボットでもあるのですが、以下のような結果になりました。ちょっとこのままでは・・・というロボットですね。
カブロボ DwRobotAdv02 が停止した後の Console の内容
■■最終成績表■■■■■■■■■■■■■■■■■■■■
--●取引データ●--------------------------------------
初期資産額(円) : 50,000,000
最終資産額(円) : 49,590,359
取引開始日 :2004-09-01
取引終了日 :2005-08-31
経過日数(日) :365
運用日数(日) :245
総トレード数 :2,060
勝ちトレード数 :788
負けトレード数 :1,272
勝率(%) :38.25
年間平均トレード数 :1491
全トレード平均期間(日) :9
勝ちトレード平均期間(日) :14
負けトレード平均期間(日) :6
最長フラット期間(日) :1
トータル約定金額(円) :2,072,549,400
--●損益データ●--------------------------------------
トータル純損益(%) :-0.82
勝ちトレード純利益(%) :24.7
負けトレード純損失(%) :-21.43
買いトレード純損益(%) :3.27
売りトレード純損益(%) :0
平均損益(%) :0.24
平均利益(%) :3.36
平均損失(%) :-1.7
年率換算利回り(%) :-0.82
最大勝ちトレード(%) :29.22
最大負けトレード(%) :-9.06
--●指標データ●--------------------------------------
平均ドローダウン(%) :3.85
最大ドローダウン(%) :6.45
損益レシオ(倍) :1.86
プロフィットファクター(倍):1.15
リスクレシオ(倍) :-0.13
年率シャープレシオ(倍) :-0.13
年率ボラティリティ(%) :6.49
■■■■■■■■■■■■■■■■■■■■■■■■■■■
|
次回予告
今回はカブロボ SDK を使って過去の株価を取得する方法を紹介しました。次回は今回の手法を更に応用して、カブロボの SDK では用意されていないテクニカル分析を自分で作ってしまおうと思っています。
著者について  | |  | 木村 桂: 日本IBM ソフトウェア事業 |
記事の評価
|