株の話題が続くと日記のアクセス数が下がる。
バックテストも熱が冷めてきた・・というより検索しても新規のストラテジーが見つからないので、暫くストップかな。
今回は、有名な「空売り」ストラテジーを実現する。
今まで、時価が狂ってしまうので実装してなかった。
前回の修正により正しく動作するようになったため、バックテストを公開する。
斎藤正章氏の手法は何度も実現しているので、氏の紹介は省略する。
話は関係ないが「https://s.wordpress.com/mshots/v1/」にアクセスしてWebサイトのサムネイルを作成していたが、作れなくなった気がする・・・。
斎藤正章の「空売りデイトレ」戦略
【銘柄選定】
- 貸借銘柄(東証一部)
【買いルール】
- 株価位置が40%以上の銘柄
- 金曜日以外の平日
- 終値基準の200日株価位置が100%より小さい場合:「50日間の株価変動率が30%以上 」
- 終値基準の200日株価位置が100%と等しい場合:「50日間の株価変動率が40%以上で終値が500円以下 」
【手仕舞い】
- 空売り戦略はデイトレ戦略なので、その日の「引け成り」で買い決済
- 「当日に引け成り買い」
株価位置って何?
過去一定期間の水準と比べて株価がどのくらいの水準にあるかを判定するための指標のこと
株価位置が50%を以上だと上昇トレンド、50%以下だと下降トレンド
- 1) 一定期間の安値を0%、高値を100%とし、この範囲での現在の株価位置を求める
- 2) 年度初めの株価を0%とし、今までの高値を100%として現在位置を求める
今回は1)を採用し次の式で求める。
(現在値 – 安値) ÷ (高値 – 安値) x 100
株価変動率って何?
株価変動率は株価の値動きの大きさを数値に直したシンプルな指標です。
いろいろな計算式が混在しており、計算式によって、同じチャートでも株価変動率の数値は全く異なってしまいます。
本に載っているストラテジーを参考にする時には、どの計算式なのかを確認しておきましょう。
- 株価変動率 =(高値-安値)÷高値 × 100(%)
- 株価変動率 =(高値-安値)÷中値 × 100(%)
- 株価変動率 =(高値-安値)÷安値 × 100(%)
- 株価変動率 =(高値-安値)÷引け値 × 100(%)
高値=期間内の最高値
安値=期間内の最安値
中値=(高値+安値)÷2
引け値=期間最終日の終値
ここでは、
株価変動率=(高値-安値)÷安値×100(%)
とした。
斎藤氏はボランティア精神旺盛で、ソースコードも公開している。
ただ、紹介しているソースコードのプログラム言語は何なの?PHP?システムトレードの達人のスクリプト?
1 2 3 4 5 6 7 8 9 10 11 12 |
// 株価位置(終値基準) if( isset($sp_position_cp['check']) ) { $this->sdi->SetWhereStockPricePositionWithEndPrice($sp_position_cp['date_num'], $sp_position_cp['val_num'], $sp_position_cp['comp']); } // 株価変動率 if( isset($change_rate['check']) ) { if( !empty($change_rate['date_num']) && !empty($change_rate['val_num']) && !empty($change_rate['comp']) ) { $this->sdi->SetWhereMovingRaito($change_rate['date_num'], $change_rate['val_num'], $change_rate['comp'], $screening_date); } } |
独自関数呼び出しているだけで、何も意味がわからないよね。
全く価値がない。
バックテスト結果
貸借銘柄だけで確かめてみる。
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 |
株価データ: 日足 銘柄リスト: 借貸(東一)20190805 1998/01/05~2020/09/04における成績です。 ---------------------------------------- 全トレード数 10134 勝ちトレード数(勝率) 5348(52.77%) 負けトレード数(負率) 4786(47.23%) 全トレード平均利率 0.15% 勝ちトレード平均利率 2.30% 負けトレード平均損率 -2.25% 勝ちトレード最大利率 38.37% 負けトレード最大損率 -32.72% 全トレード平均期間 1.68 勝ちトレード平均期間 1.66 負けトレード平均期間 1.71 ---------------------------------------- 必要資金 ¥3,078,700 最大ポジション(簿価) ¥3,000,000 最大ポジション(時価) ¥3,275,400 純利益 ¥6,708,600 勝ちトレード総利益 ¥52,914,800 負けトレード総損失 -¥46,206,200 全トレード平均利益 ¥662 勝ちトレード平均利益 ¥9,894 負けトレード平均損失 -¥9,654 勝ちトレード最大利益 ¥198,000 負けトレード最大損失 -¥142,000 プロフィットファクター 1.15 最大ドローダウン(簿価) -¥556,900 最大ドローダウン(時価) -¥556,900 ---------------------------------------- 現在進行中のトレード数 7 ---------------------------------------- 平均年利 10.38% 平均年利(直近5年) 13.38% 最大連勝 12回 最大連敗 10回 ---------------------------------------- [年度別レポート] 年度 取引回数 運用損益 年利 勝率 PF 最大DD 2020年 339回 ¥580,700円 18.86% 56.93% 1.34倍 -23.51% 2019年 493回 ¥151,600円 4.92% 54.16% 1.07倍 -14.87% 2018年 513回 ¥823,400円 26.75% 55.17% 1.36倍 -11.58% 2017年 512回 ¥234,500円 7.62% 56.64% 1.11倍 -15.31% 2016年 497回 ¥269,500円 8.75% 55.13% 1.12倍 -16.40% 2015年 497回 ¥175,300円 5.69% 57.34% 1.07倍 -19.85% 2014年 487回 ¥36,300円 1.18% 56.47% 1.02倍 -11.85% 2013年 491回 ¥225,300円 7.32% 58.66% 1.09倍 -20.10% 2012年 481回 ¥468,400円 15.21% 60.29% 1.21倍 -17.95% 2011年 476回 ¥470,300円 15.28% 59.45% 1.20倍 -23.15% 2010年 459回 ¥45,200円 1.47% 59.48% 1.02倍 -19.53% 2009年 486回 ¥635,400円 20.64% 59.47% 1.31倍 -13.54% 2008年 480回 ¥202,300円 6.57% 56.04% 1.08倍 -28.77% 2007年 495回 -¥44,600円 -1.45% 54.34% 0.98倍 -23.41% 2006年 488回 ¥694,600円 22.56% 61.27% 1.41倍 -13.46% 2005年 512回 -¥2,300円 -0.07% 60.35% 1.00倍 -19.57% 2004年 489回 ¥524,400円 17.03% 61.55% 1.24倍 -32.72% 2003年 486回 ¥504,300円 16.38% 63.58% 1.22倍 -16.67% 2002年 465回 ¥19,500円 0.63% 57.20% 1.01倍 -20.62% 2001年 484回 ¥148,100円 4.81% 58.47% 1.06倍 -19.51% 2000年 504回 ¥546,400円 17.75% 58.73% 1.24倍 -16.75% |
利益曲線は次のとおりです。
お!ほぼ単調増加を実現できた。
まとめ
少し利益が低いなぁ。
手数料負けになるので、手数料無料しか使えない。
「株価位置」「株価変動率」「前日比と一定以上」の値を変更すれば良いかもしれない。
でも、今となっては、もっと利益の出るストラテジーは沢山あるかな。
【参考】ソースコード
いつも通り独自ライブラリの取り込みが必要。
実装は次のようになります。
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 |
# loop-type: date-only //============================== require "TIlib" require "Utility" require "TrendCheck" //============================== // 斎藤正章の「空売りデイトレ」戦略 //============================== // //[対象銘柄] //①東証1部の貸借銘柄 // //[仕掛けルール] //①終値が前日比で一定以上高くなっていて当日が陽線 //②株価位置が40%以上の銘柄 //③金曜日以外の平日 //⑤終値基準の200日株価位置が100%より小さい場合:「50日間の株価変動率が30%以上 」 //⑥終値基準の200日株価位置が100%と等しい場合:「50日間の株価変動率が40%以上で終値が500円以下 」 // //[手仕舞いルール] //⑦「当日に引け成り買い」 // 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 = 1 // 最大保有日数 $shortSelling = 1 // 空売り戦略 Yes(1)/No(0) $Interest = 1 // 無制限(0) / 単利(1) / 複利(2) $reverse = 0 // 購入順序 昇順(0) / 降順(1) $udcount = 0 // 騰落レシオ利用数 Init() //------------------------------------------------ $HL200 = [$code_num] $HL50 = [$code_num] $HL10 = [$code_num] // 値上がり銘柄のカウント ------------------------ InitDone() // 騰落レシオ初期化 $__INIT__ = 1 end def Main(i) //================================================== // 条件(買条件, 売条件共通部分) //================================================== //まだ上場していない銘柄は株価データがないためnullが返る if (Index == null) return end if ! ($order[(int)Code]) $order[(int)Code] = i end //================================================== if ! ($HL200[i] && $HL50[i] && $HL10[i]) $HL200[i] = HighLow_new(200) $HL50[i] = HighLow_new(50) $HL10[i] = HighLow_new(10) $hold[i] = 0 return end //指標の計算を1日進める HighLow_next($HL200[i]) HighLow_next($HL50[i]) HighLow_next($HL10[i]) // ここまで ======================================== //================================================== // 保有してない→購入 //================================================== if ! ($hold[i]) high10 = HighLow_high($HL10[i]) low10 = HighLow_low($HL10[i]) high50 = HighLow_high($HL50[i]) low50 = HighLow_low($HL50[i]) high200 = HighLow_high($HL200[i]) low200 = HighLow_low($HL200[i]) if ! (high10 && low10 && high50 && high50 && high200 && low200) return end if ! (Close && {-1}Close && {-2}Close && {-3}Close) return end // 株価50円以下は省く if (Close <= 50) return end // 終値基準の200日株価位置 if (high200 == low200) stock_pos = 0 else stock_pos = (float)(Close - low200) / (high200 - low200) * 100 end // ① 終値が前日比で一定以上(4%)高くなっていて当日が陽線 check1 = Close > ({-1}Close * 1.04) && Close > Open // ② 株価位置が40%以上の銘柄 check2 = stock_pos >= 40 // ③ 金曜日以外の平日 check3 = DayOfWeek != 5 if ! (check1 && check2 && check3) return end // 50日間の中値 mid50 = (high50 - low50) / 2 // 株価変動率 stock_var = (float)(high50 - low50) / low50 * 100 // PrintLog("stock_var = " + stock_var) //4) 終値基準の200日株価位置が100%より小さい場合 // 50日間の株価変動率が30%以上 check4 = stock_pos < 100 && stock_var >= 30 //5) 終値基準の200日株価位置が100%と等しい場合 // 50日間の株価変動率が40%以上で終値が500円以下 check5 = stock_pos == 100 && stock_var >= 40 && Close <= 500 if (check4 || check5) $buyflag[i][0] = 1 // 購入フラグ $buyflag[i][1] = stock_var // 好きなパラメータをもとにソート $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) $sellflag[i] = 1 $set[i] = 0 end end end //==================== // 売り処理(デイトレ模倣) //==================== def Sell_(i) if ($sellflag[i]) if ({-1}Close) SellingLimitedPrice(i, 0, {-1}Close) else if (Open) // 翌々日の始値で売るが、日付は翌日にする SellingLimitedPrice(i, 0, Open) else Print("銘柄データ異常") // 翌々日の始値もない SellingLimitedPrice(i, 0, {-2}Close) end end $sellflag[i] = 0 end // 使用した$buyflag 配列を初期化 if ($buyflag[i][0]) $buyflag[i][0] = 0 $buyflag[i][1] = 0 end end //==================== // 買い処理 //==================== def SortBuy(i) if (PricedataExistCheck(Close)) return end $long = 0 $long = Num($buyUnit, Close) codeset = $order[(int)Code] if (HasPricedata({1}Open)) Buying(codeset) 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 if ($buyCnt) BuyLoop(1, 1, codes) end //==================== // 売り //==================== i = -1 while i + 1 < $code_num i = i + 1 {codes[i]}Sell_(i) end |