20年間の日経平均株価を見てると、株価上がってるのに2017年ぐらいからシステムトレードのバックテストは寝てしまう。
(C)会社四季報 2020年夏号(巻頭18ページ)
私だけじゃないからね。
システムトレーダー全員の悩みだと思ってる。
何度か紹介しているが坂本タクマ氏なんて2010年ぐらいから横ばいだよ……。
これはセンスがない。
(C)坂本タクマ / 第29話「シストレあるあるの”資産横ばい”を脱出せよ!」
でも、最近はバフェットの言うとおり「S&P500」で良いんじゃない?とも思えてきた。
少なくとも確定拠出年金などは全てアメリカ株にしておこう。
以前書いたようにシステムトレードは長期保有・スイング投資からデイトレ・分足買い・高速トレードにシフトしてる……ように感じている。
まぁコロナや大震災など未曾有の危機による株価下落は心理的に耐えれないので、デイトレに飛びつくのは理解できる。
デイトレ手法も身につけるため、cosisin氏がストラテジーを公開しているので、氏のバックテストから行ってみよう。
cosisin氏のブレイクアウトデイトレサンプル有効性検証
黒塗りとなっているが、二つ後のブログで答えを公開している。
最後にブレイクアウトはスイングにしない方が良さそうです。勝率激減、マイナスの年出現といいとこなしです。まあ、それでもそれを何とかしようとする努力が大切なんでしょうね。
ブレイクアウトとは、株価がレジスタンスラインを上抜けること。
その他の売買ルールは次のとおり。
【基本設定】
- 1) 株価の低い場合はランキングしない[50]円以下
- 2) 売買代金の少ない場合はランキングしない(売買代金の[3]日間平均が[5]千万円以下の場合)
- 3) 単利利用、通年
- 4) 全ての銘柄対象
【ランキング条件(ブレイクアウトサンプル)】
- 1) [前日比(率)]が[-5]と[5]の[範囲内]
- 2) 過去[2]日間に、[終値→高値(率)]が[8]より[大きい(同じ含む)]日が[1]日以上[存在しない]
【買いルール】
- 1) [ブレイクアウトサンプル(順位)]が[10]より[小さい(同じ含む)]
- 2) [翌日逆指値(終日)][終値(+5.00%)]で[買い]を仕掛ける
【手仕舞いのルール】
- 1) [Stop高(高値)]が[1]と[同じ]
- 1.1) [当日指定値][高値]で手仕舞いする
- 2) [保有日数]が[1]より[大きい(同じ含む)]
- 2.1) [当日引け]で手仕舞いする
【優先順設定】
- 1) 期間上昇(率)(10)大きい順
イザナミ独自のネーミングが幾つかある。次のような式になる。
「終値→高値(率)」= ((高値÷終値)-1) × 100
「期間上昇(率)」= 当日終値(現在値) ÷ 指定期間前の終値 × 100
なお、手仕舞いルールの1つ目は実装していたがシンプル化のために削除した。
バックテスト結果
何度か買い/売りの実装を修正したよ……。
そしてバックテスト時間は8時間、長げーよ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
株価データ: 日足 銘柄リスト: 全銘柄 1998/01/05~2021/04/26における成績です。 ---------------------------------------- 全トレード数 7677 勝ちトレード数(勝率) 4576(59.61%) 負けトレード数(負率) 3101(40.39%) 全トレード平均利率 2.47% 勝ちトレード平均利率 8.52% 負けトレード平均損率 -6.45% 勝ちトレード最大利率 64.02% 負けトレード最大損率 -45.79% 全トレード平均期間 2.98 勝ちトレード平均期間 3.00 負けトレード平均期間 2.97 ---------------------------------------- 必要資金 ¥2,409,900 最大ポジション(簿価) ¥2,996,600 最大ポジション(時価) ¥4,024,800 純利益 ¥82,911,780 勝ちトレード総利益 ¥175,172,900 負けトレード総損失 -¥92,261,120 全トレード平均利益 ¥10,800 勝ちトレード平均利益 ¥38,281 負けトレード平均損失 -¥29,752 勝ちトレード最大利益 ¥326,700 負けトレード最大損失 -¥235,200 プロフィットファクター 1.90 最大ドローダウン(簿価) -¥634,300 最大ドローダウン(時価) -¥863,300 ---------------------------------------- 現在進行中のトレード数 3 ---------------------------------------- 平均年利 156.38% 平均年利(直近5年) 148.66% 最大連勝 18回 最大連敗 13回 ---------------------------------------- [年度別レポート] 年度 取引回数 運用損益 年利 勝率 PF 最大DD 2021年 105回 ¥2,162,692円 89.74% 69.52% 2.94倍 -21.50% 2020年 371回 ¥3,633,181円 150.76% 57.14% 1.76倍 -24.91% 2019年 365回 ¥3,306,032円 137.19% 59.73% 1.83倍 -29.83% 2018年 369回 ¥5,066,509円 210.24% 64.77% 2.54倍 -21.57% 2017年 395回 ¥3,744,200円 155.37% 59.24% 1.77倍 -26.02% 2016年 393回 ¥4,075,407円 169.11% 57.00% 1.68倍 -34.20% 2015年 406回 ¥3,915,600円 162.48% 53.45% 1.72倍 -28.44% 2014年 424回 ¥5,560,100円 230.72% 58.96% 1.92倍 -25.81% 2013年 438回 ¥4,361,000円 180.96% 55.02% 1.50倍 -30.34% 2012年 397回 ¥3,846,500円 159.61% 59.19% 1.71倍 -30.09% 2011年 390回 ¥4,813,500円 199.74% 57.69% 1.98倍 -24.60% 2010年 367回 ¥4,064,544円 168.66% 60.49% 1.91倍 -22.24% 2009年 346回 ¥2,766,800円 114.81% 60.12% 1.54倍 -32.35% 2008年 373回 ¥3,658,180円 151.80% 65.15% 1.90倍 -31.67% 2007年 368回 ¥2,998,500円 124.42% 60.33% 1.70倍 -22.53% 2006年 283回 ¥2,781,150円 115.41% 64.66% 2.06倍 -20.49% 2005年 387回 ¥3,323,766円 137.92% 59.95% 1.79倍 -31.75% 2004年 355回 ¥3,207,000円 133.08% 62.54% 1.77倍 -37.50% 2003年 336回 ¥4,173,400円 173.18% 67.86% 2.42倍 -22.62% 2002年 267回 ¥3,351,600円 139.08% 68.16% 2.42倍 -31.71% 2001年 303回 ¥4,571,500円 189.70% 75.58% 3.21倍 -45.79% 2000年 239回 ¥3,530,600円 146.50% 75.73% 3.85倍 -16.96% |
利益曲線は次のとおり。
勝率60%未満、プロフィットファクタ2.0未満……だけど
平均年利(直近5年) 148.66%
えぇぇ元本が2倍になるのwww??
デイトレで一銘柄の平均利益「¥10,800」って、凄すぎるでしょww
まとめ
ついに来た!!
私の時代が!!
とか思ってない。
なんせ、cosisin氏のブログに次のように書いてある。
ブレイクアウトのサンプルを作りました。当然質を落としています。それでもまずまずな感じにしています。
氏の結果とも違うしね。
また不具合の可能性が高いけど……よく分からない……。
とりあえず、毎日フォワードテストしながら状況をウォッチしてみるか……。
Protraは実装の自由度が高すぎて、実装が合ってるのか色々と心配になってくる。
ソースコード
バックテストには無料OSSの「Protra」を利用した。
TIlib、Utility、TrendCheckライブラリはGitHubに置いている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# loop-type: date-only //============================== require "TIlib" require "Utility" require "TrendCheck" // ====================================== // cosisin氏のブレイクアウトデイトレサンプル戦略 // ====================================== // http://blog.livedoor.jp/cosisin/archives/10382289.html // // 【基本設定】 // // 1) 株価の低い場合はランキングしない[50]円以下 // 2) 売買代金の少ない場合はランキングしない(売買代金の[3]日間平均が[5]千万円以下の場合) // 3) 単利利用、通年 // 4) 全ての銘柄対象 // // 【ランキング条件(デイトレ逆張りサンプル)】 // // 1) [前日比(率)]が[-5]と[5]の[範囲内] // 2) 過去[2]日間に、[終値→高値(率)]が[8]より[大きい(同じ含む)]日が[1]日以上[存在しない]// // // 【買いルール】 // // 1) [デイトレ逆張りサンプル(順位)]が[10]より[小さい(同じ含む)] // 2) [翌日逆指値(終日)][終値(+5.00%)]で[買い]を仕掛ける // // 【手仕舞いのルール】 // // 1) [Stop高(高値)]が[1]と[同じ] // 2) [当日指定値][高値]で手仕舞いする // 3) [保有日数]が[1]より[大きい(同じ含む)] // 4) [当日引け]で手仕舞いする // // 【優先順設定】 // // 1) 期間上昇(率)(10)大きい順 codes = CodeList if ($code_num && $code_num != Length(codes)) Print("前回と異なる銘柄リストでは実行できません。") Dummy end $code_num = Length(codes) //グローバル変数を初期化 if (!$__INIT__) $budgetIni = 3000000 $buyUnit = 500000 // 1回の購入資金 (50万円) $MaxHoldDay = 0 // 最大保有日数 $shortSelling = 0 // 空売り戦略 Yes(1)/No(0) $Interest = 1 // 無制限(0) / 単利(1) / 複利(2) $reverse = 1 // 購入順序 昇順(0) / 降順(1) $udcount = 0 // 騰落レシオ利用数 Init() //------------------------------------------------ //------------------------------------------------ InitDone() // 騰落レシオ初期化 $__INIT__ = 1 end // [期間上昇(率)]=[当日終値(現在値)]÷[指定期間前の終値] def PeriodUpRate(i) if ! ({-1 * i}Close) return 0 end return (float)Close / (float){-1 * i}Close * 100 end def Main(i) //================================================== // 条件(買条件, 売条件共通部分) //================================================== //まだ上場していない銘柄は株価データがないためnullが返る if (Index == null) $hold[i] = 0 return end if ! ($order[(int)Code]) $order[(int)Code] = i end //================================================== // 保有してない→購入 //================================================== if (! $hold[i]) if ! (Close && {-1}Close && {-2}Close && {-3}Close && High && {-1}High && {-2}High) return end if ! (Volume && {-1}Volume && {-2}Volume) return end //================================================== // 選定 //================================================== // 1) 株価の低い場合はランキングしない[50]円以下 // 2) 売買代金の少ない場合はランキングしない(売買代金の[3]日間平均が[5]千万円以下の場合) if (SalesValue()/3 + {-1}SalesValue()/3 + {-2}SalesValue()/3 <= 50000 || Close <= 50) return end //================================================== // 売買(買い) //================================================== // 1) [前日比(率)]が[-5]と[5]の[範囲内] // 2) 過去[2]日間に、[終値→高値(率)]が[8]より[大きい(同じ含む)]日が[1]日以上[存在しない] // 前日比(率) = (終値 - 1日前の終値) ÷ 1日前の終値 × 100 // 終値→高値(率)= ((高値÷終値)-1)×100 day1 = (Close - {-1}Close) / {-1}Close * 100 day2 = ((High / Close) - 1) * 100 day3 = (({-1}High / {-1}Close) - 1) * 100 day4 = (({-2}High / {-2}Close) - 1) * 100 if (5 > Abs(day1) && 8 > day2 && 8 > day3 && 8 > day4) $buyflag[i][0] = (int)(Close * 1.05) // 購入額 $buyflag[i][1] = PeriodUpRate(10) // 期間上昇(率)(10)大きい順 $buyflag[i][2] = $buyflag[i][0] $buyCnt = $buyCnt + 1 end //================================================== // 保有している→売却 //================================================== elsif ($hold[i]) if ($set[i] < 1) $set[i] = 1 return end $set[i] = $set[i] + 1 //================================================== // 売買(売り) //================================================== if ($set[i] >= $MaxHoldDay) PrintLog("利益確定") $sellflag[i] = 1 $set[i] = 0 end end end def CheckHighLow2(t) t = Yobine(t, 0) if ! ({1}High > t && t > {1}Low) return 0 end if (t > {1}Open) return {1}Open else return t end end //================================================== // 買い(指値) //================================================== def Buying2(i) if (HasPricedata({1}Open) && HasPricedata(Close)) t = 0 if ($buyflag[i][0]) t = CheckHighLow2($buyflag[i][0]) end if (t) BuyingLimitedPrice(i, 1, t) end end end //==================== // 買い処理 //==================== def SortBuy(i) PrintLog("購入予定") if ! (HasPricedata(Close)) return end $long = 0 $long = Num($buyUnit, Close) codeset = $order[(int)Code] Buying2(codeset) end //==================== // 売り処理(デイトレ模倣) //==================== def Sell_(i) if (HasPricedata(Open)) if ($sellflag[i]) if ({-1}Close) SellingLimitedPrice(i, 0, {-1}Close) else PrintLog("売れない") end $sellflag[i] = 0 $buyflag[i][2] = 0 end // 使用した$buyflag 配列を初期化 if ($buyflag[i][0]) $buyflag[i][0] = 0 $buyflag[i][1] = 0 end end end //==================== // 銘柄コードを変えながらMain関数,BuySell関数を実行 //==================== Print("-------------------------------------------------") Print("日付 = "+ Year + "/" + Month + "/" + Day) SortInit() // ソート初期化 i = -1 while (i + 1 < $code_num) i = i + 1 {codes[i]}Main(i) end i = -1 while (i + 1 < $code_num) i = i + 1 {codes[i]}Sort(i) end i = -1 if ($buyCnt) // 1) [デイトレサンプルスイング改良版(順位)]が[10]より[小さい(同じ含む)] $buyCnt = $buyCnt % 10 + 1 while i + 1 < $buyCnt i = i + 1 {$sortList2[i]}SortBuy(i) end end //---------------------------------------------- i = -1 while (i + 1 < $code_num) i = i + 1 {codes[i]}Sell_(i) end |