レベル: 上級 木村 桂 (kimuc@jp.ibm.com), ソフトウェア事業, IBM
2007年 5月 25日 スーパー・カブロボ・コンテストの Java プログラミング上級編も第3回目を迎えました。前回は「過去の株価を取得する方法」を紹介しましたが、今回はこれを応用してカブロボ SDK で用意されていないテクニカル手法を実装したロボットを作ります。具体的には「サイコロジカルライン」というテクニカル手法を取り上げます。
カブロボ SDK で用意されているテクニカル手法を利用するだけであれば株価そのものを知る必要はないのですが、実際に株価は上がっているのか下がっているのか、という基本的な情報を得る上で、是非知っておきたい方法だと思っています。またカブロボ SDK で用意されていないテクニカル手法を使いたい場合には、過去の株価をもとに自分で計算する必要がありますから、その場合でもやはり過去の株価を知る方法が必要になります。
本題の前に1つ連絡事項があります。スーパー・カブロボを Java 言語で開発するためのカブロボ SDK が、正式にバージョン 2.0 となりました。本連載ではバージョン 2.0 の RC(リリース候補)版を使って紹介してきましたが、今回からは改めて正式な SDK を使って紹介します。処理速度の向上といった変更も含まれていますので、皆さんも最新版の SDK をダウンロードして、利用してください。互換性については大きな変更はないのですが、正式版ではロボット作成後のテスト実行の期間が 2006 年の(1月4日から12月29日までの)1年間に変更になったこともあって、この期間を変更せずにテストした場合の実行結果は今までに本連載で紹介してきたものとは異なる可能性があります。その点のみご注意ください。
「サイコロジカルライン」
今回は「サイコロジカルライン」というテクニカル手法を使います。突然ですが第1回スーパー・カブロボ・コンテストにはなんと小学生も参加されていました。ということで、もしかしたらこの記事もそんな未来のスーパー・トレーダーの予備軍である方も読んでいるかも・・・ ということで、簡単にサイコロジカルラインの説明をしておきます。
サイコロジカル・ラインは「サイコロ」とは何の関係もありません。でも「サイコロ」と、省略して呼ぶ大人もいます。大人って不思議ですね。 このサイコロジカルラインは「心理的な一線」という意味を持つテクニカル手法の1つです。簡単に言うと「こんなに下がったら、そろそろ上がるだろう」とか「こんなに上がったら、そろそろ下がるだろう」という人間の心理を投資の判断に用いる手法です。
ここで「こんなに下がったら」とか「こんなに上がったら」と言いましたが、どうやってその判断をするのでしょうか? サイコロジカルラインでは特定期間(通常は直近の12日間)中の終値だけを見比べて、前日終値よりも当日終値の方が高かった日を「上昇日」としてカウントします。そしてこの期間中で上昇日は全体の何%あったかを計算したものをサイコロジカルラインと呼びます。
実はこの考え方は上級編(1)で紹介した RSI に非常に似ています。RSI は特定期間中の終値の推移を値幅単位で比較します。そして上昇した幅は変化全体(=上昇した幅+下落した幅)の何%あったかを計算したものが RSI になります。一方、サイコロジカルラインは値動きが 1 円であっても 100 円であっても同じ上昇日としてカウントし、その上昇日の割合を計算することになります。以下に5日間のデータを元に、最終日のサイコロジカルラインと RSI それぞれの計算例を載せておきますが、こうして比較してもかなり似ていることが分かると思います。
同じ5日間の終値データに基づく、4日間のサイコロジカルラインと RSI の計算例
|
| 終値 | 前日終値との差 | サイコロジカルライン | RSI |
|---|
| 0 | 2006 |
|
|
| | 1 | 1998 | -8 |
|
| | 2 | 2007 | +9 |
|
| | 3 | 1987 | -20 |
|
| | 4 | 2015 | +27 | 50% ※1 | 56.25% ※2 |
| ※1: | この4日間で前日よりも株価が上昇したのは2日間(下落したのも2日間)。したがってサイコロジカルラインの値は 2/4 = 0.5 = 50% | | ※2: | この4日間の前日終値との差で上昇した分だけの合計は 9 + 27 = 36、下落した分だけの合計は 8 + 20 = 28 したがって RSI の値は 36 / ( 36 + 28 ) = 0.5625 = 56.35% |
今回はこのサイコロジカルラインを使った売買判断を行うロボットを作ってみます。現在のカブロボ SDK にはサイコロジカルラインを求める機能は存在していないので、前回の記事を参考に過去の株価を取得して、自分でサイコロジカルラインを計算した上で売買判断をさせてみます。
サイコロジカルラインを元に売買銘柄を判断するロボット
では実際にロボットを作ってみます。今回作成するロボットの基本戦略は上級編(1)の RSI ロボットとの比較の意味で、
- 12日間のサイコロジカルラインの値が 30% を超えたら買いのサインと見なす
- 12日間のサイコロジカルラインの値が 70% を下回ったら売りのサインと見なす
とします。つまり上級編(1)のロボットの判断で使っている RSI をサイコロジカルラインに変えただけです。
DwRobotAdv03.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 DwRobotAdv03 extends AbstractRobot {
private final int PSY_N = 12; //. サイコロジカルラインを計算する日数 (1)
@Override
public void order(TradeAgent arg0) {
// TODO Auto-generated method stub
//. 省略(DwRobot04 の order メソッドと同じ)
}
@Override
public void screening(TradeAgent arg0) {
// TODO Auto-generated method stub
//. 当日の日付と PSY_N 営業日前の日付を取得
Calendar c0 = arg0.getTimeManager().getCurrentDate(); //. 当日
Calendar c2 = arg0.getTimeManager().getBusinessDay( -1 * ( PSY_N + 1 ) );
//. PSY_N 営業日前 (2)
//. 売買の候補リストを用意
ArrayList<Stock> buyList = new ArrayList<Stock>(); //. 買い候補
ArrayList<Stock> sellList = new ArrayList<Stock>(); //. 売り候補
//. このシミュレーションで取引できる全株銘柄を取得する
ArrayList<Stock> stockList = arg0.getInformationManager().getStockList();
//. 個別に銘柄を1つずつ取得して、サイコロジカルラインの値をチェックする
for( Stock stock : stockList ){
//. この銘柄の、過去 ( PSY_N + 1 ) 日間の株データを取得する (3)
ArrayList<StockData> stockDataList
= arg0.getInformationManager().getStockDailyByInterval( c2, c0, stock );
//. この銘柄の、過去 ( PSY_N + 1 ) 日間の終値を取得する (4)
int cp[] = new int[PSY_N+1];
int i = 0;
for( StockData stockData : stockDataList ){
cp[i++] = stockData.getClosingPrice();
}
//. 終値の前日差を求める (5)
int dif[] = new int[PSY_N];
for( i = 0; i < PSY_N; i ++ ){
dif[i] = cp[i] - cp[i+1];
}
//. 前日と当日のサイコロジカルラインの値を求める (6)
double psy[] = new double[2];
for( int j = 0; j < 2; j ++ ){
int pcnt = 0, ncnt = 0;
for( i = j; i < j + PSY_N - 1; i ++ ){
if( dif[i] >= 0 ){
pcnt ++;
}else{
ncnt ++;
}
}
//. 期間中、終値が上昇した日の割合を求める (7)
psy[j] = 100.0 * ( double )pcnt / ( pcnt + ncnt );
}
if( psy[1] <= 30.0 && 30.0 <= psy[0] ){
//. 前営業日から今日にかけてサイコロジカルライン値が 30.0 を超えた場合は、買い注文の候補
buyList.add( stock );
}else if( psy[1] >= 70.0 && 70.0 >= psy[0] ){
//. 前営業日から今日にかけてサイコロジカルライン値が 70.0 を下回った場合は、売り注文の候補
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", "DwRobotAdv03" };
RobotDriver.main( arg );
}
}
|
今回も前回同様に order メソッドの内容は DwRobot04 と同じものを利用することにしますので省略します。
一方、screening メソッドでは最初に株価を取得する日付の範囲を決定しています。TimeManager クラスの getCurrentDate() メソッドでまず当日の日付を取得します(1)。そして get BusinessDay() メソッドで当日から指定営業日だけ前後させた日付を取得します。指定営業日だけさかのぼる場合は営業日を負の数で指定しますので、12営業日前の日付は当日も含めると13日前になるので、-13 をパラメータ指定する点に注意してください(2)。
ところで、今回は 12 日間のサイコロジカルラインを計算しますが、なぜ 12 営業日前の日付を求めるか分かりますか?12営業日前までのデータを求めると当日も含めて13個のデータが得られます。でも今回のサイコロジカルラインは 12 個のデータがあれば計算できます。この1つの差は何でしょう? 実のところ、当日のサイコロジカルラインの値を計算するだけであれば12個のデータで充分です。ただ今回はサイコロジカルライン値が 30% を上回ったか/70% を下回ったか、といった判断をすることになるので、当日だけでなく前営業日時点でのサイコロジカルラインの値も計算する必要があるのです。前営業日時点でのサイコロジカルラインは当日分の計算で使うよりも更に1つ前のデータが必要になります。その結果、全部で 13 個のデータが必要になっています。皆さんがご自身で同様のロジックを作成する場合はこの点に注意してください。
この後、DwRobot04 と同様に売買候補のリスト変数を管理する変数を用意した上で全銘柄を取得し、個別にループさせて売買候補かどうかを判断します。
判断の内容は各銘柄の(当日から12営業日前まで)直近13日分の株価データを取得します。具体的には InformationManager クラスの getStockDailyByInterval メソッドを範囲日付と銘柄クラスをパラメータ指定して実行することで取得できます(3)。プログラム上ではこの結果を stockDataList というリスト変数に格納していますが、このリストには13個の(13日分の)データが含まれることになります。なお、このリストには新しい順にデータが格納される点に注意してください。
株価データのリストを取得したら、13日分の終値を cp という配列変数に取得します(4)。リストには新しい順にデータが格納されているので cp[0] が最も最近の(つまり当日の)終値、cp[12] が最も古い(つまり12営業日前の)終値ということになります。ここまでは一応説明も加えましたが、上級編(2)で紹介した DwRobotAdv02 とほぼ同様です。
ここからが今回の新しいロジックになります。取得した終値を元に自分でサイコロジカルラインの値を計算します。サイコロジカルラインでは終値の前日比が上昇しているか下落しているかが重要になるので、まずは一日ごとの終値の差を dif という配列変数に求めておきます(5)。
ここまでの準備ができたらサイコロジカルラインの値を計算します。今回は比較のため前営業日時点でのサイコロジカルライン値と当日のサイコロジカルライン値の2つを求める必要がありますから、サイコロジカルライン値を格納する変数もやはりサイズは2の配列変数: psy を用意することにします。そして当日の値を psy[0] に、前営業日時点での値を psy[1] に格納することにします(6)。計算の内容は単純で、12日間に渡って dif の値が正(前日比増)か、負(前日比減)かを判断し、それぞれの数をカウントします。そして上昇日が全体の何%あったかを計算したものをサイコロジカルライン値として格納しています(7)。
ちなみに、当日のサイコロジカルライン値 psy[0] は dif[0] から dif[11] までの12個の配列変数で計算し、前日の値 psy[1] は dif[1] から dif[12] までを使って計算することになります。そしてこれらの計算方法は非常に似ているので j という変数を使ったループでまとめて計算するようにしています。Java の初心者の方には少し難しいかもしれませんが、こういった方法でプログラミングを効率化している、と理解してください。
最後にこうして求められた psy[0] と psy[1] の値を上級編(1)で使った RSI と同様に比較して、買い/売り銘柄の判断を行い、オブジェクトメモにそれぞれ格納しています。これが今回のロボットの内容になります。
このロボットを実行した結果が以下になります。今回からは SDK 2.0 の正式版を使っていますので、取引期間は 2006-01-04 から 2006-12-29 までの1年間に変更になっています(過去と同じ 2004-09-01 から 2005-08-31 までの期間で実行されたい方は robot-config.xml を変更してください)。結果論や運もあるとはいえ、勝率が 60% を超えるなかなかのロボットになりました。
カブロボ DwRobotAdv03 が停止した後の Console の内容
■■最終成績表■■■■■■■■■■■■■■■■■■■■
--●取引データ●--------------------------------------
初期資産額(円) : 50,000,000
最終資産額(円) : 53,058,842
取引開始日 :2006-01-04
取引終了日 :2006-12-29
経過日数(日) :359
運用日数(日) :248
総トレード数 :272
勝ちトレード数 :171
負けトレード数 :101
勝率(%) :62.87
年間平均トレード数 :272
全トレード平均期間(日) :31
勝ちトレード平均期間(日) :30
負けトレード平均期間(日) :32
最長フラット期間(日) :1
トータル約定金額(円) :399,383,300
--●損益データ●--------------------------------------
トータル純損益(%) :6.12
勝ちトレード純利益(%) :18.27
負けトレード純損失(%) :-11.39
買いトレード純損益(%) :6.89
売りトレード純損益(%) :0
平均損益(%) :1.04
平均利益(%) :6.92
平均損失(%) :-8.94
年率換算利回り(%) :6.04
最大勝ちトレード(%) :20.54
最大負けトレード(%) :-16.48
--●指標データ●--------------------------------------
平均ドローダウン(%) :1.82
最大ドローダウン(%) :7.6
損益レシオ(倍) :0.95
プロフィットファクター(倍):1.6
リスクレシオ(倍) :0.8
年率シャープレシオ(倍) :0.75
年率ボラティリティ(%) :8.09
■■■■■■■■■■■■■■■■■■■■■■■■■■■
|
感想と次回予告
今回紹介したような
- 過去のデータを取得して、
- 自分で独自に計算して売買判断する
というロボットは、ある意味でとても重要だと思っています。それはカブロボがオープンなコンテスト形式で開催されている理由の1つに「新しい投資手法の発見」があるだけでなく、投資家やエンジニアの個性をアピールする部分であるとも考えているからです。
今回はサイコロジカルラインという、たまたま現在のカブロボ SDK では用意されていなかったものの、判断基準としては一般的に確立されたテクニカル手法を紹介しました。しかし興味があったら是非挑戦してほしいのは、「全く新しい、自分オリジナルの投資手法」です。このカブロボ SDK はそれを可能にするツール(道具)であると思っています。
次回は少しテクニカル手法からは離れて、カブロボ SDK に搭載されている外国為替情報の取得方法や、その情報を元にした銘柄売買を行うようなロボットを紹介する予定です。
著者について  | |  | 木村 桂: 日本IBM ソフトウェア事業 |
記事の評価
|