前回で、一旦 実運用の夢は散ったので、再度、ひたすら実装して検証することを続けます。
「仕掛け優先順位(ソート)」「騰落レシオ」などが有志達のおかげでProtraで実装できたため、今までにバックテストができなかった手法の実現が可能となりました。
保田望氏とは?
保田望氏は、早稲田大学商業学部を卒業し、日本生命保険相互会社を経て、2004年にマネーカレッジを創業しています。
その後、2006年に独立系投資会社を創業しています。
分かりやすく説明するとシステムトレード「検証くん」の製作者です。
そして、28歳の時点で、システムトレードの3年5ヶ月の結果、5億円の資産を築きました。
書籍の中で次のように語られています。
「有効な売買ルールを聞いて、その通りにトレードをしさえすれば、次の日からでも儲けられる」というものがシステムトレードの本質だと勘違いしている人たちが、意外にも多くいます。
どんなにシステムトレードが優れた手法だと言っても、システムトレードの挑戦者の中でも勝ち組と負け組は出てきます。
そして、その勝ち組と負け組は「システムトレードの本質をどのくらい理解してマーケットに臨めるか」で決まってきます。
売買ルール
逆張り型の売買ルールでは「移動平均乖離率」「ストキャスティクス」を利用しています。
- 1) 25日移動平均乖離率がマイナス20%以下
- 2) ストキャスティクス%K(Fast K)(9日)が30%以下
- 3) ストキャスティクス%D(Slow D)(9日)が30%以下
【危険銘柄と流動性のない銘柄を排除する】
書籍には売買ルールを構築するまでの考え方(プロセス)が丁寧に記載されています。
- 4) 当日終値が100円以上
- 5) 10日間平均売買代金が1000万円以上
いつ倒産してもおかしくないような危険銘柄を排除し、流動性のない銘柄はシステムトレードに向いていないので排除しています。
【一律で決まった銘柄数という突入タイミングではなく、過去の売買シグナル数との相対比較で決める】
- 4) 突入タイミング 過去120日平均サイン点灯数の4倍以上
これにより、暴落が珍しい局面ではシグナル数が少な目でも突入してくれます。
また暴落が当たり前のように起こっている局面では、シグナル数がかなり多くないと突入してくれなくなります。
ようするに、逆張りが機能する可能性が高い局面では出てきた売買シグナルに対して積極的にトレードし、逆張りが機能しにくい可能性が高い局面では出てきた売買シグナルを保守的に見るという柔軟な突入タイミングになります。
ソースコード
書籍では初期資金500万円、最大リバレッジ1.5倍、ポジションサイズは資金の10分の1で実装されています。
ここでは、1000万円の資金でポジションサイズは10部の1で実装しています。
コードは長いです。「突入タイミング」の概念の実装で頭を悩ませましたが、Protraで実現可能でした。
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 |
# loop-type: date-only //============================== require "TIlib" require "Utility" require "TrendCheck" //============================== // 株式投資「システムトレード」の極意(保田望 著) //============================== // // 下記のルールに従い、10日間平均売買代金が大きい順に仕掛ける // // 【資金管理条件】 // 1) 初期資金 500万円 // 2) 最大レバレッジ 1.5倍 // 3) ポジションサイズ 資金の10分の1 // 4) 突入タイミング 過去120日平均サイン点灯数の4倍以上 // // 【買いルール】 // 1) 25日移動平均乖離率がマイナス20%以下 // 2) ストキャスティクス%K(Fast K)(9日)が30%以下 // 3) ストキャスティクス%D(Slow D)(9日)が30%以下 // 4) 当日終値が100円以上 // 5) 10日間平均売買代金が1000万円以上 // //【手仕舞いルール】 // 1) 買い付けた日から60日が経過 // 2) 株価(終値)が買値よりも2%以上上昇 codes = CodeList if $code_num && $code_num != Length(codes) Print("前回と異なる銘柄リストでは実行できません。") Dummy end $code_num = Length(codes) //グローバル変数を初期化 if ! ($__INIT__) $budgetIni = 10000000 $budget = $budgetIni // 投資総額 (1000万円) $buyUnit = 1000000 // 1回の購入資金 (100万円) $MaxHoldDay = 45 // 最大保有日数 $Interest = 1 // 無制限(0) / 単利(1) / 複利(2) $reverse = 1 // 購入順序 昇順(0) / 降順(1) $ratiodate = 0 // 騰落レシオ日数 //------------------------------------------------ $BB = [$code_num] $ST = [$code_num] //------------------------------------------------ $signal = [120] // 過去120日平均サイン $sflag = 0 // 平均サインのフラグ i = 0 while (i < 120) $signal[i] = -1 i = i + 1 end Init() $__INIT__ = 1 end def Main(i) //================================================== // 条件(買条件, 売条件共通部分) //================================================== //まだ上場していない銘柄は株価データがないためnullが返る if (Index == null) return end if ! ($order[(int)Code]) $order[(int)Code] = i end if ! ($BB[i] && $ST[i]) //銘柄ごとのグローバル変数を初期化する $BB[i] = BB_new(25) $ST[i] = Stoch_new(9, 3, 3) $hold[i] = 0 return end //指標の計算を1日進める BB_next($BB[i]) Stoch_next($ST[i]) // ここまで ======================================== if (1 == PricedataExistCheck(Close)) return end //================================================== // 保有してない→購入 //================================================== if (! $hold[i]) ma = BB_value($BB[i]) st_k = Stoch_k($ST[i]) st_d = Stoch_d($ST[i]) tv = TradingValume(10) if ! (ma && st_k && st_d && Close) return end r = 100 * (Close - ma) / ma // 4) 当日終値が100円以上 // 5) 10日間平均売買代金が1000万円以上 if ! (Close >= 100 && tv >= 10000) return end // 1) 25日移動平均乖離率がマイナス20%以下 // 2) ストキャスティクス%K(Fast K)(9日)が30%以下 // 3) ストキャスティクス%D(Slow D)(9日)が30%以下 if (r <= -20 && st_k <= 30 && st_d <= 30) PrintLog("tv=" + tv) $buyflag[i][0] = 1 // 10日間平均売買代金(株価 x 出来高)が大きい順に仕掛ける $buyflag[i][1] = tv $buyCnt = $buyCnt + 1 end //================================================== // 保有している→売却 //================================================== elsif ($hold[i]) if ($set[i] < 1) $set[i] = 1 return end $set[i] = $set[i] + 1 //================================================== // 売買(売り) //================================================== // 2) 株価(終値)が買値よりも2%以上上昇 if (Close >= 1.02 * $buy[i]) PrintLog("利食い") $sellflag[i] = 1 $set[i] = 0 // 1) 買い付けた日から60日が経過 elsif ($set[i] >= $MaxHoldDay) PrintLog("損切り") $sellflag[i] = 1 $set[i] = 0 end end end //==================== // 買い処理 //==================== def SortBuy(i) if (PricedataExistCheck(Close)) return end $long = 0 $long = Num($buyUnit, Close) codeset = $order[(int)Code] Buying(codeset) end //==================== // 売り処理 //==================== def Sell_(i) if (PricedataExistCheck(Close)) return end if ($sellflag[i]) Selling(i) $sellflag[i] = 0 end end // ========================================= // 過去の平均サイン点灯数を返す&120日の更新 // ========================================= def SignalCount() $signal[$sflag] = $buyCnt $sflag = ($sflag + 1) % 120 i = 0 sum = 0 while (i < 120) if ($signal[i] == -1) return 9999 end sum = sum + $signal[i] i = i + 1 end return sum / 120 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 // 4) 突入タイミング 過去120日平均サイン点灯数の4倍以上 sg = SignalCount() Print("過去120日平均サイン点灯数 =" + sg + " $sflag=" + $sflag) if ($buyCnt >= sg * 4) 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 |
バックテスト結果
計算時間は2.5時間です。
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 |
株価データ: 日足 銘柄リスト: 全銘柄 1998/01/05~2019/08/09における成績です。 ---------------------------------------- 全トレード数 869 勝ちトレード数(勝率) 723(83.20%) 負けトレード数(負率) 146(16.80%) 全トレード平均利率 3.70% 勝ちトレード平均利率 7.70% 負けトレード平均損率 -16.10% 勝ちトレード最大利率 38.75% 負けトレード最大損率 -63.25% 全トレード平均期間 14.52 勝ちトレード平均期間 8.44 負けトレード平均期間 44.65 ---------------------------------------- 必要資金 ¥9,633,500 最大ポジション(簿価) ¥9,999,900 最大ポジション(時価) ¥11,411,200 純利益 ¥29,724,510 勝ちトレード総利益 ¥50,680,220 負けトレード総損失 -¥20,955,700 全トレード平均利益 ¥34,205 勝ちトレード平均利益 ¥70,097 負けトレード平均損失 -¥143,532 勝ちトレード最大利益 ¥381,600 負けトレード最大損失 -¥643,500 プロフィットファクター 2.42 最大ドローダウン(簿価) -¥2,488,200 最大ドローダウン(時価) -¥3,793,100 ---------------------------------------- 現在進行中のトレード数 0 ---------------------------------------- [年度別レポート] 年度 取引回数 運用損益 勝率 PF 最大DD 2000年 30回 ¥207,200円 86.67% 1.11倍 -62.57% 2001年 73回 ¥3,726,400円 89.04% 4.19倍 -57.74% 2002年 58回 ¥1,792,900円 86.21% 1.78倍 -59.17% 2003年 27回 ¥2,376,900円 92.59% 221.08倍 -0.64% 2004年 49回 ¥1,382,400円 83.67% 1.84倍 -63.25% 2005年 42回 ¥2,891,437円 88.10% 9.10倍 -12.43% 2006年 85回 ¥3,279,800円 88.24% 3.23倍 -33.60% 2007年 56回 ¥1,714,300円 83.93% 3.51倍 -40.86% 2008年 47回 -¥1,170,500円 65.96% 0.59倍 -55.81% 2009年 41回 ¥973,000円 85.37% 1.70倍 -51.46% 2010年 20回 -¥443,300円 70.00% 0.62倍 -44.71% 2011年 28回 ¥2,040,700円 89.29% 21.15倍 -6.76% 2012年 20回 ¥689,000円 85.00% 5.86倍 -9.98% 2013年 44回 ¥1,474,100円 72.73% 1.81倍 -32.58% 2014年 62回 ¥2,948,600円 83.87% 4.08倍 -30.70% 2015年 30回 ¥966,767円 76.67% 1.96倍 -30.98% 2016年 42回 ¥2,281,139円 95.24% 31.91倍 -4.27% 2017年 48回 ¥1,025,800円 81.25% 2.21倍 -22.73% 2018年 62回 ¥1,528,470円 87.10% 2.64倍 -35.09% 2019年 5回 ¥39,400円 80.00% 1.23倍 -17.81% |
利益曲線は次のとおりです。
綺麗な単調増加をしています。マイナスだった年は過去20年間で2回しかありません。
まとめ
年利15.6%で、最大DDは63.25%です。グラフを見ると最大DD(時価)が大きそうです。このままでは実運用で耐えるのは難しそうです。
この時代に「動的フィルタ」の概念が存在したことは驚きです。
なお、最後に筆者はさらなるリスクヘッジを次のように記載しています。
【資金を分割して投入する(1度の暴落で投入する資金を制限する)】
例えば、資金500万円で運用していた場合、1度目の暴落では資金の5分の1にあたる100万円で仕掛けます。
そしてその後、再び暴落が起きたら、また100万円で仕掛け、合計200万円のポジションを持ちます。
そこから更なる暴落が起きたら3回目、4回目といったぐらいに突入タイミングを時間的に分散させることによって、リスクを遥かに低減させることができます。
ここまで、多くの書籍やインターネット上の実装を実現してきて、全てProtraで実装可能だということが分かりました。
それを証明する目的でソースコードを公開してきましたが、その役割は達成したかと思ってます。
今後は、実運用目指して、検討を進める事も進めたいです。