株式投資でプログラミング!パート❹ ー ”新値買い"の後、どの程度保有していると儲かるか、コーディングで解明!
必勝の「カップパターン」を見つける!
前回Part 3では”カップパターン”を検知するところまでコーディングを進めました。例えばアップル株(AAPL)の場合、2017年以降でカップパターンは6回見つかりました。つまり、ある時点の株価からずるずると下がっていって、そこからスルスルと値を上げて新高値を更新したパターンです。でもカップを見つけるだけでは何も面白くはありません。新値更新は買いのタイミングでしたよね。つまり、新値更新で株を買うと儲かるということ。
本当にそうなのでしょうか。
そこでこれから次の点をプログラミングで調べてみます。
✅ カップパターンはどの程度続くとみるべきか
✅ 新値更新で株を買ったとして、どの程度保有しておくとよいのか
✅ カップの深さというのは関係しているのか
そして最終的には、どのようなカップパターンを見つけると新値買いが儲けにつながるのか、その”勝率”をもとにベストの投資パターンを見つけてみます。
新値買い後に株は本当に上がるのか?
まず、過去のカップパターンを見つけたら、そこで株を買ったと仮定します。そして何日間か保有していたらどの程度儲かるかというのを「試算」してみます。
前回見つけたアップル株のカップの一つはこんなものでした。
Found a cup!!
Starting High: 164.050003
Starting Date: 2017/09/01
New High: 166.720001
New Date: 2017/10/30
Bottom Price: 142.729996
Bottom Day: 2017/07/06
Cup Length: 40
17年9月に付けた高値から40日間はその高値を更新せず、10月30日に$166の新高値を更新し、その間、$142まで値を下げたパターンです。ではこの10月30日に$142でアップル株を買ったとします。これで儲けが出るかどうかは当然「いつ売るか」次第です。そこで、「新値で買ってX日間い持っていたらいくら上がるか・下がるか」というのをチェックする関数を作ってみます。
”タラレバ関数”、GetHypeGainを作る
例えば保有期間を30日とすると、10月30日に$142で買ったとして、だいたい11月30日くらいの株価を調べて上がっているかどうかチェックすることになりますが、ここで一つ考えてみてください。株価データで〇〇日というのは平日のみだということに気づいていましたか?一週間は5日営業日しかないので、30日というのは1か月ではなく約1か月半に相当するのです。
これを踏まえて、新値買いの日付とその時の株価を入れるとX日後の値上がり・値下がり具合を計算してくれるGetHypGain関数を作ります。GetHypGainというのはGet Hypothetical Gain (仮定の儲け額を取得する)ということです。言ってみればタラレバの計算です。
そこで作った関数をご覧ください。
private static double GetHypGain(DateTime investDate, double purchasePrice, int holdDays, List<HistoryPrice> history)
{
double sellPrice = 0.0;
foreach (var data in history)
{
//新値買いの日付からX日後となったらその日の値段を取る
if (data.Date > investDate.AddDays(holdDays))
{
//この日の値段が売り値
sellPrice = data.Close;
//差を返して終わり
return sellPrice - purchasePrice;
}
}
return 0.0;
}
まずパラメータですが、新値買いの日付と値段をinvestDate, purchasePriceとしています。
private static double GetHypGain(DateTime investDate, double purchasePrice, int holdDays, List<HistoryPrice> history)
その上で保有期間、holdDayを入れます。例えば営業日ベースで40日間、つまり期間では2か月を指定するなら40という数字を入れます。ここで注目するのはhistoryデータ(詳しくはPart 3をご覧ください)をドバっとぶち込んでいるところです。10月30日から営業日で40日後というと、この大本のデータがないとわかりません。そこで指定した期間のすべてのデータをこの関数に渡します。
さて関数の中で何をやるかというと、historyデータをザーッと読み込んでいって、新値買いの日付からholdDay日後に株価がどれくらいになったか調べます。それがわかったらすぐに引き算をしてその結果を返します。新値買い日付+holdDay以降はスキャンする必要がないので、IF文で売る日付がわかったらそこで処理は終わりということになります。あまり効率の良い処理ではありませんが、とりあえず目的は達成できます。
各カップの「儲け率」を調べてみる!
ではこの関数を組み込んで、カップの情報に新値買いからの上昇率を表示させてみます。コード全体はこうなります。主な変更箇所は、GetHypGain関数を除くと2か所です。
using System;
using System.Collections.Generic;
namespace CupAndHandle
{
class Program
{
static void Main(string[] args)
{
//過去の株価を取得
var prices = YahooFinanceAPI.GetStockPrices
("AAPL", new DateTime(2008, 7, 1), new DateTime(2020, 7, 1));
//====================
//株価を一日づつ見ていく
//====================
double HighPrice = 0;//とりえあえず0に設定
DateTime HighDate = new DateTime(2019, 7, 1);
double LowPrice = 1000000; //とりあえず百万ドルに設定
DateTime LowDate = new DateTime(2019, 7, 1);
int CupDays = 0; //カップの長さを記録する
//カップ情報のパラメータ
int HoldLength = 40;
int CupLength = 60;
foreach (var pricetoday in prices)
{
//もし今日の株価が過去最高より高かったらカップチェック
if (pricetoday.Close > HighPrice)
{
//もしX日より長かったらカップ!
if (CupDays > CupLength)
{
//カップ情報をひょじする
Console.WriteLine("Found a cup!!");
Console.WriteLine("Starting High: " + HighPrice.ToString());
Console.WriteLine("Starting Date: " + HighDate.ToShortDateString());
Console.WriteLine("New High: " + pricetoday.Close.ToString());
Console.WriteLine("New Date: " + pricetoday.Date.ToShortDateString());
Console.WriteLine("Bottom Price: " + LowPrice.ToString());
Console.WriteLine("Bottom Day: " + LowDate.ToShortDateString());
Console.WriteLine("Cup Length: " + CupDays.ToString());
double hypGain = GetHypGain(pricetoday.Date, pricetoday.Close, HoldLength, prices);
double hypGainRate = hypGain / pricetoday.Close * 100;
Console.WriteLine("Hyp Gain Rate: " + hypGainRate.ToString());
Console.WriteLine();
}
//リセット
HighPrice = pricetoday.Close;
HighDate = pricetoday.Date;
LowPrice = 1000000;
LowDate = pricetoday.Date;
CupDays = 0;
}
//もし今日の株価が最高値更新しなかったらスキャンを継続
else
{
//最安値チェック
if (LowPrice > pricetoday.Close)
{
LowPrice = pricetoday.Close;
LowDate = pricetoday.Date;
}
}
//CupDaysカウンタを一つ上げる
CupDays++;
}
Console.ReadLine();
}
private static double GetHypGain(DateTime investDate, double purchasePrice, int holdDays, List<HistoryPrice> history)
{
double sellPrice = 0.0;
foreach (var data in history)
{
//新値買いの日付からX日後となったらその日の値段を取る
if (data.Date > investDate.AddDays(holdDays))
{
//この日の値段が売り値
sellPrice = data.Close;
//差を返して終わり
return sellPrice - purchasePrice;
}
}
return 0.0;
}
}
}
まずカップの長さと保有期間をパラメータ化した
カップの長さと保有期間を簡単に指定できるようにパラーメータかしました。
//カップ情報のパラメータ
int HoldLength = 40;
int CupLength = 60;
カップの長さを60日としたのは、営業日60日というのは四半期に相当します。つまり値が下がって戻るまで少なくとも四半期をかけているカップだけを見るためです。この四半期もとりあえずの値ではありますが、決算発表の間隔はカップが続くべきだという考えで選んでいます。つまり新たな評価が出てくる可能性は次の決算発表まで待たないといけないとうのはそれなりに意味があると思います。
そして新値買い後の保有期間は2か月、営業日数にして40日としてみます。
新値買い後の値動きを計算する
GetHypGainを使って新値と新値日付、そして先ほど指定したHoldLengthを指定して株価の上下を見ます。それを新値買いの株価と比較して値下がり率・値上がり率を計算します。
double hypGain = GetHypGain(pricetoday.Date, pricetoday.Close, HoldLength, prices);
double hypGainRate = hypGain / pricetoday.Close * 100;
Console.WriteLine("Hyp Gain Rate: " + hypGainRate.ToString());
Mainのすぐ下には先ほど解説したGetHypGain関数を入れてあります。
では実際にApple株の例で新値買いの勝率をみていきましょう!
2008年7月以降ではAppleの新値買いは7勝1敗!
「3か月カップ」の発生は8回。そのうち「2か月保有」して売ったとしたらどうなっていたか?12年9月からほぼ2年続いた超特大カップの時以外はすべて勝利!上昇率は2%から11%です。
Found a cup!!
Starting High: 25.65
Starting Date: 2008/07/08
New High: 25.981428
New Date: 2009/09/16
Bottom Price: 11.171429
Bottom Day: 2009/01/20
Cup Length: 301
Hyp Gain Rate: 8.522576203278737
Found a cup!!
Starting High: 39.152859
Starting Date: 2010/06/18
New High: 39.509998
New Date: 2010/09/16
Bottom Price: 34.275715
Bottom Day: 2010/08/24
Cup Length: 62
Hyp Gain Rate: 11.30275430537859
Found a cup!!
Starting High: 51.875713
Starting Date: 2011/02/16
New High: 52.131428
New Date: 2011/07/15
Bottom Price: 45.045715
Bottom Day: 2011/06/20
Cup Length: 103
Hyp Gain Rate: 2.4114915862270285
Found a cup!!
Starting High: 90.889999
Starting Date: 2012/04/09
New High: 90.905716
New Date: 2012/08/16
Bottom Price: 75.73143
Bottom Day: 2012/05/17
Cup Length: 91
Hyp Gain Rate: 4.532162752010009
Found a cup!!
Starting High: 100.300003
Starting Date: 2012/09/19
New High: 100.529999
New Date: 2014/08/19
Bottom Price: 55.790001
Bottom Day: 2013/04/19
Cup Length: 480
Hyp Gain Rate: -0.41778375030124765
Found a cup!!
Starting High: 133
Starting Date: 2015/02/23
New High: 133.289993
New Date: 2017/02/13
Bottom Price: 90.339996
Bottom Day: 2016/05/12
Cup Length: 498
Hyp Gain Rate: 5.69435996594283
Found a cup!!
Starting High: 232.070007
Starting Date: 2018/10/03
New High: 236.210007
New Date: 2019/10/11
Bottom Price: 142.190002
Bottom Day: 2019/01/03
Cup Length: 257
Hyp Gain Rate: 10.922485176506529
Found a cup!!
Starting High: 327.200012
Starting Date: 2020/02/12
New High: 331.5
New Date: 2020/06/05
Bottom Price: 224.369995
Bottom Day: 2020/03/23
Cup Length: 79
Hyp Gain Rate: 0
注目してほしいのは8つ目のカップは先月上旬にできたばっかりのもので、その時に買っていたら今(7月10日時点)はもうすでに15%も値が上がっています!もし最新のカップも含めて、来月まで値がもてば、Appleのカップパターンは8勝1敗となります。
次回のPart 5では
今回は発見したカップの情報をもとに「仮想投資勝率」なるものを調べる関数とコーディングを解説しました。確かにAppleの株価でみると新値買いは確かに勝率の高い投資判断なのでしょうが、他の株はどうでしょうか。ハイテク株以外のセクターでも同様の傾向があるのか。さらにもっと勝率が上がるカップの見つけ方はないのか。こういったことを掘り下げていこうと思います。
引き続き乞うご期待!
この記事が気に入ったらサポートをしてみませんか?