 | レベル: 上級 木村 桂 (kimuc@jp.ibm.com), ソフトウェア事業, IBM
2006年 3月 10日 過去4回の連載では、ある程度のテクニカル分析の知識がある方向けの記事を書いてきましたが、この第5回では少し見直し、これからテクニカル分析を行う方にも比較的理解しやすいテクニカル指標を紹介します。いわば入門編です。
テクニカルの入門
というわけで、今回は十字線を扱ってみます。同時線と呼ばれることもあるそうです。この十字線はテクニカル分析的には入門編に分類されることが多いと思いますが、カブロボ SDK によるアルゴリズム化を考えると決して単純なわけではありません。
なお、以下の説明では「十字線」という表記で統一することにします。
また毎回繰り返しておりますが、ここで紹介する投資方法が絶対的に正しいというわけではなく、技術の紹介であることをあらかじめご了承願います。投資判断は自己責任にてお願いいたします。
十字線
この十字線というのは、4本値による株価グラフを作成した場合に漢数字の「十」のような形が現れる現象を意味しています。一般的に相場の転換期を意味する、と言われています。
株価は取引時間の中で刻一刻と推移していきます。日本の一般的な取引では朝9時に取引が始まり、昼の休憩を挟んで午後3時に終了します。この間に株の需要と供給が一致して売買が成立する度に、その時の取引価格が「株価」として決まります。朝9時の取引開始後に最初に成立した取引の株価を「始値」、午後3時の取引終了前最後に成立した取引の株価を「終値」と呼びます。また一日の中で最も高い値段で成立した株価を「高値」、最も低い値段で成立した株価を「安値」と言います。
そしてこれら「始値」、「高値」、「安値」、「終値」の4つの値のことを「4本値」と呼びます。また、この4つの値の関係が分かるようにグラフを記述する方法の1つにローソク足があります。一日の中で終値が始値よりも高い場合、つまり1日の結果として値が上がった場合は陽線ローソク足を、逆に値が下がった場合は陰線ローソク足を用います。
このローソク足を記述する際、特に
- 始値と終値がほぼ同じ
- 始値(≒終値)が、高値と安値の中間とほぼ同じ
という2つの条件が揃うと、この日のローソク足は漢数字の「十」という字に似た形になります。これが十字線です。
ところで、例えばここ数日ずっと株価が上昇(あるいは下落)していた銘柄に対して、この十字線が現れる時というのは、
- 一日の売買の結果、値がほとんど変わらない
- ただし高値も安値も存在しているため、売買量が少なくて動かないわけではない
という状態になっていることから、買おうとしている人と、売ろうとしている人の考えている値段がほぼ拮抗している状態になっている、と考えることができます。
そうだとすると、ずっと上昇基調・下落基調できていた株価もそろそろ一段落して、反対側に動き始めるきっかけではないか?とみなせるのではないか、というのがこの十字線を使ったテクニカル分析の考え方です。つまり結論として一般に言われている「十字線が現れたら相場は転換する」というのは、以上のような仮説に基づいていることになります。
今回はこの考えをカブロボの投資に応用して、「十字線が現れたら、今までとは逆の値動きをする」と判断して、その方向で売買を行う、というアルゴリズムを実装してみることにします。
アルゴリズム化
この十字線、アルゴリズム化においては1つ難しい点があります。プラス記号のような十字というのは人間の目で見て「十」という漢数字に見えるため簡単に判断できますが、コンピュータには十字かどうかをどのように判断させればよいでしょうか?
ここはあまり深く考えても仕方ないので、今回は以下のような調査を行うことにしました。毎日、各銘柄で以下の3つの数字を指標として計算します:
| (1) 始値と終値の差 | … |
ここの差が小さいほど横棒が一本のきれいな線になるので、十字に近くなる
|
| | (2) (高値と安値の中間値)と終値の差
| … |
ここの差が小さいほど縦線の中間部分に近い位置で横線が重なる形になるので、やはり十字に近くなる
|
| | (3) 高値と安値の差 | … |
この差が大きいほど価格が上下しつつ最終的に十字に収まっている、ということを意味するので、転換期である可能性が高い
|
まず最優先に(1)を見ます。(1)がゼロになっていれば、きれいな横棒が記載されていることになるので、十字の最低条件を満たします。そこで(1)が最も小さい銘柄を選びます。
この(1)の選別で複数の銘柄が候補に残った場合は(2)をみます。この(2)の値がゼロになっていれば、ちょうどプラス記号のように互いに中間点同士で線が重なるような十字が描かれていることになります。そこで(1)で選別しきれなかった場合は(2)が最も小さい銘柄を選びます。
これでもまだ複数の銘柄が候補に残った場合は(3)を見ます。形は十字であっても、全体的により縦に長い十字を選ぼう、ということです。(2)でも選別しきれなかった場合は(3)の値が最も大きな銘柄を選びます。
毎営業日にこの方法で売買対象銘柄を1つ特定し、前日と当日の終値を比較して上昇中なのか下落中なのかを判断し、その反対方向の売買注文を出します。また「十字線は転換のサイン」であることを信じて、この注文は翌営業日に決済することにします。このアルゴリズムを実装してみましょう。
Java のプログラムで実装
ここまでに決めたアルゴリズムを実際の Java プログラムで記述してみたのが、以下のソースコードになります。ここでは run メソッドの中身だけを紹介しています:
public void run(InvestmentAgent arg0) {
// TODO Auto-generated method stub
Stock[] stocks = arg0.getStocks(); // 銘柄リストの取得
int N = stocks.length; // 銘柄リスト数(今回のルールでは常に 100 のはず)
int i, idx, lvl, tradetype = 0;
double mindiff, mindiff2, maxdiff3;
long[] op = new long[N];
long[] hp = new long[N];
long[] lp = new long[N];
long[] cp = new long[N];
//. ポートフォリオを取得
InformationManager infoManager = arg0.getInformationManager();
Portfolio portfolio = arg0.getPortfolio();
Map holdingMap = portfolio.getHoldings();
// 前営業日に注文した株があれば決済する
if( holdingMap.size() > 0 ){
//. 前営業日に注文した銘柄の情報を取得
Iterator itr = holdingMap.values().iterator();
Holding holding = ( Holding )itr.next();
// 決済なので、注文した内容が買いであれば売り、売りであれば買いの注文を行う
if( holding.getNumber() > 0 ){
tradetype = StockOrder.SELL;
}else{
tradetype = StockOrder.BUY;
}
// 決済注文
SimpleStockOrder stockOrder = new SimpleStockOrder();
stockOrder.setStock( holding.getStock() ); // 注文の銘柄を設定
stockOrder.setLimitType( StockOrder.MARKET ); // 成り行き注文
stockOrder.setTradeType( tradetype ); // 買い/売り注文を設定
stockOrder.setQuantity( 1 ); // 注文を1単位株に設定
arg0.order( stockOrder ); // 注文の発行
}
// 各銘柄について4本値を求めて、十字に近い形になっているかどうかを調べる。
Calendar cdt = Time.getTime(); // 当日の日付
for( i = 0, idx = -1, lvl = 0, mindiff = 10000000000.0, mindiff2 = 100000000.0, maxdiff3
= -10000000.0; i < N; i ++ ){
List list = infoManager.getIndexInformation( stocks[i], cdt, -1 );
IndexInformation indexInformation = ( IndexInformation )list.get( 0 ); // 前日のデータ
// 4本値(始値、高値、安値、終値)を求める 0
op[i] = indexInformation.getOpeningPrice();
hp[i] = indexInformation.getHighPrice();
lp[i] = indexInformation.getLowPrice();
cp[i] = indexInformation.getClosingPrice();
// (1)始値と終値の差を求める 1
double diff1 = ( double )( ( op[i] < cp[i] ) ? ( cp[i] - op[i] ) : ( op[i] - cp[i] ) ) / cp[i];
// (2)(高値と安値の中間値)と終値との差を求める 2
double mp = ( double )( hp[i] + lp[i] ) / 2;
double dcp = ( double )cp[i];
double diff2 = ( ( mp < dcp ) ? ( dcp - mp ) : ( mp - dcp ) ) / 2;
// (3)高値と安値の差を求める 3
double diff3 = ( double )( hp[i] - lp[i] );
// これら2つの差の積が最も小さいものを求める 4
if( diff1 == 0.0 ){
if( diff2 == 0.0 ){
// (1)も(2)もゼロである銘柄は最優先と考え、(3)で比較する
if( diff3 > maxdiff3 ){
idx = i;
maxdiff3 = diff3;
}
lvl = 2;
}else{
// (1)のみゼロの場合は、(2)で比較する
if( lvl < 2 ){
if( diff2 < mindiff2 ){
idx = i;
mindiff2 = diff2;
}
lvl = 1;
}
}
}else{
// (1)がゼロでない場合、(1)×(2)の数値が小さいものを選ぶ
if( lvl == 0 ){
double diff = diff1 * diff2;
if( diff < mindiff ){
idx = i;
mindiff = diff;
}
}
}
}
if( idx > -1 ){
// 前日の終値と比較して、買い注文か売り注文かを決定する
List list = infoManager.getIndexInformation( stocks[idx], cdt, -2 );
IndexInformation indexInformation0 = ( IndexInformation )list.get( 0 ); // 一昨日のデータ
long cp0 = indexInformation0.getClosingPrice();
IndexInformation indexInformation1 = ( IndexInformation )list.get( 1 ); // 昨日のデータ
long cp1 = indexInformation1.getClosingPrice();
// 終値の動きを比較し、株価が逆行するという推測で注文する 5
if( cp0 <= cp1 ){
// 上がっていたら売り
tradetype = StockOrder.SELL;
}else{
// 下がっていたら買い
tradetype = StockOrder.BUY;
}
System.out.print( "注文銘柄: " + stocks[idx].getName() + "(" + stocks[idx].getCode() );
System.out.println( "\tOHLC: " + cp[idx] + ", " + hp[idx] + ", " + lp[idx] + ", " + cp[idx] );
SimpleStockOrder stockOrder = new SimpleStockOrder();
stockOrder.setStock( stocks[idx] ); // 注文の銘柄を設定
stockOrder.setLimitType( StockOrder.MARKET ); // 成り行き注文
stockOrder.setTradeType( tradetype ); // 買い/売り注文を設定
stockOrder.setQuantity( 1 ); // 注文を1単位株に設定
arg0.order( stockOrder ); // 注文の発行
}
}
|
以下、このプログラムについて簡単に紹介しますが、決済部分については今まで紹介してきた例と同様ですので、説明を省略します:
-
(0) 各銘柄につき、ローソク足が十字型になっているかどうかを調べるため、その日の4本値(始値、高値、安値、終値)を取得します。
-
(1)(始値と終値の差)を求めます。
-
(2)((高値と安値の中間値)と終値の差)を求めます。
-
(3)(高値と安値の差)を求めます。
-
(1)、(2)、(3)を比較して、ローソク足が最も十字の形に近いであろう銘柄を特定します。
-
特定された銘柄に対して、前日から本日にかけての価格推移を見て、上昇していれば売り、下落していれば買いの注文を発行します。
シミュレーション結果
このプログラムを実行すると以下のような結果になります。シミュレート期間は 2005 年の4月です:
■1日目2005/04/01 金 終了時の所持金額
総資産 = 手持ち資金+所有株式時価総額 = 5,000,000円
手持ち資金(運転可能金額 + ロック金額) = 5,000,000円
運転可能金額 = 5,000,000円
ロック資金 = 0円
単純計算年率利益率 0.0%
○ロボットの銘柄評価
注文銘柄: 新生銀(8303 OHLC: 607, 609, 604, 607
購入: 8303 新生銀 1単位 成行
【注文処理結果】
銘柄名|銘柄コード| 枚数| 購入価格| 前日比
------------------------------+----------+----------+----------+----------
新生銀| 8303| 1000| 605| 7
【ポートフォリオ】
銘柄名|銘柄コード| 枚数| 購入価格| 前日比
------------------------------+----------+----------+----------+----------
新生銀| 8303| 1000| 605| 7
実行時間: 3.078 秒.
■2日目2005/04/02 土 終了時の所持金額
No Data
実行時間: 0.0 秒.
■3日目2005/04/03 日 終了時の所持金額
No Data
実行時間: 0.0 秒.
■4日目2005/04/04 月 終了時の所持金額
総資産 = 手持ち資金+所有株式時価総額 = 4,995,000円
手持ち資金(運転可能金額 + ロック金額) = 4,395,000円
運転可能金額 = 4,395,000円
ロック資金 = 0円
単純計算年率利益率 -36.0%
○ロボットの銘柄評価
売却: 8303 新生銀 1単位 成行
注文銘柄: 東ガス(9531 OHLC: 430, 432, 429, 430
売却: 9531 東ガス 1単位 成行
【注文処理結果】
銘柄名|銘柄コード| 枚数| 購入価格| 前日比
------------------------------+----------+----------+----------+----------
新生銀| 8303| -1000| 598| 2
東ガス| 9531| -1000| 428| -1
【ポートフォリオ】
銘柄名|銘柄コード| 枚数| 購入価格| 前日比
------------------------------+----------+----------+----------+----------
東ガス| 9531| -1000| 428| -1
実行時間: 1.5 秒.
:
:
(略)
:
:
■28日目2005/04/28 木 終了時の所持金額
総資産 = 手持ち資金+所有株式時価総額 = 5,018,000円
手持ち資金(運転可能金額 + ロック金額) = 4,752,000円
運転可能金額 = 4,752,000円
ロック資金 = 0円
単純計算年率利益率 6.0%
○ロボットの銘柄評価
売却: 4004 昭電工 1単位 成行
注文銘柄: ANA(9202 OHLC: 340, 341, 339, 340
売却: 9202 ANA 1単位 成行
【注文処理結果】
銘柄名|銘柄コード| 枚数| 購入価格| 前日比
------------------------------+----------+----------+----------+----------
昭電工| 4004| -1000| 265| -2
ANA| 9202| -1000| 341| -1
【ポートフォリオ】
銘柄名|銘柄コード| 枚数| 購入価格| 前日比
------------------------------+----------+----------+----------+----------
ANA| 9202| -1000| 341| -1
実行時間: 1.781 秒.
■29日目2005/04/29 金 終了時の所持金額
No Data
実行時間: 0.0 秒.
■30日目2005/04/30 土 終了時の所持金額
No Data
実行時間: 0.0 秒.
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
【最終結果】
あなたのロボットによる、該当期間の運用成績は、こちらです。
総資産 = 手持ち資金+所有株式時価総額 = 5,017,000円
単純計算年率利益率 6.0%
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
|
ここ最近2回は精度のいいテクニカル分析ばかり紹介してきたせいか、なんとも微妙な結果に見えますが、とりあえずプラスになりました。
今回はどちらかというと、凝ったテクニカル分析の紹介というよりは、テクニカル分析としては基本的なものである一方、「十字の形に見えるかどうか?」というあいまいな判断も含まれるためアルゴリズム化が難しいケースをアルゴリズム化する例として紹介しました。この十字線は(私自身は眉唾モノだと思っていますが)ローソク足の初心者向け説明の中でもよく紹介されているため、聞いたことのある人は多いのではないでしょうか?
確かに人間には簡単に(形を見て直感的に)理解できるテクニカル指標であるとは思いますが、だからといってプログラムによるアルゴリズム化が簡単なわけではない、といういい例だと思います。
著者について  | |  | 木村 桂: 日本IBM ソフトウェア事業 |
記事の評価
|  |