本日、誕生日です。
何もしてませんが、会社を休みました。
早く不老不死と若返りの薬が発明されて欲しいです。
Protraは自由度が高いので取り込んだ株価を参照するのであれば、何でも実装可能です。
このため、誤実装は頻繁に起きます。
結論からいうと、完全なミスなソースコードでしたが、正しくコーディングしても、あまり良い結果が出なかったので、ミスのまま紹介します。
gorotanhccat氏が「シンプルでそこそこ儲かるデイトレ売り戦略」として紹介しています。
TOさんが売り戦略を考えているようなので、とってもシンプルでそこそこ儲かるデイトレ売り戦略を公開しましょう。
まず、ユーザー定義で下の画像のものを作ります。前日比を3日乖離率や高値→終値などに
変えても構いません。計算期間も好きなように変えてください。
当日手仕舞い、翌日始値を見た上での指値などが入っています。
gorotanhccat氏の売りデイトレ戦略の有効性検証
イザナミの独自設定が出てきており、私の解釈が正しいのかよく分かりません。
[ランキング条件]
- 1) 売上代金が100万円より大きい(おなじを含む)
- 2) 東証1部騰落レシオ(3)が[100]より[小さい]
- 3) 貸借銘柄
[買いルール]
- 1) [ランキング条件]の中で[5日間の前日比(率)]が最小から[5]つ抽出
- 2) [翌日始値]が[終値(+10.00%)]より[小さい]場合、[翌日指値寄付]が、終値(-2.50%)で[売り]を仕掛ける
- 3) [翌日始値]が[終値(+10.00%)]より[大きい]場合、[翌日逆指値(終日)][翌日始値(-1Tick)]で[売り]を仕掛ける
[手仕舞いルール]
- 1) [Stop高(高値)]が[1]と[同じ]場合、[当日指定値][高値]で手仕舞い
- 2) [Stop安(安値)]が[1]と[同じ]でない場合、[当日引け]で手仕舞いする
- 3) [Stop安(安値)]が[1]と[同じ]場合、[当日指定値][安値(+1Tick)]で手仕舞いする
貸借銘柄一覧はイザナミの「https://izanami.page.link/taisyaku」に存在します。
翌日指値(寄付)は、翌日寄付のみ有効な指値で仕掛けます( 証券会社への注文方法: 指値 – 寄付 )。
買い注文の場合、翌日始値が指値以下なら約定したものとして検証します。
ソースコード
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 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
# loop-type: date-only //============================== require "TIlib" require "Utility" require "TrendCheck" // ====================================== // gorotanhccat氏のシンプルでそこそこ儲かるデイトレ売り戦略 // ====================================== // //[ランキング条件] //1) 売上代金が100万円より大きい(おなじを含む) //2) 東証1部騰落レシオ(3)が[100]より[小さい] //3) 貸借銘柄 // //[買いルール] //1) [ランキング条件]の中で[5日間の前日比(率)]が最小から[5]つ抽出 //2) [翌日始値]が[終値(+10.00%)]より[小さい]場合、[翌日指値寄付]が、終値(-2.50%)で[売り]を仕掛ける //3) [翌日始値]が[終値(+10.00%)]より[大きい]場合、[翌日逆指値(終日)][翌日始値(-1Tick)]で[売り]を仕掛ける // //[手仕舞いルール] //1) [Stop高(高値)]が[1]と[同じ]場合、[当日指定値][高値]で手仕舞いする //2) [Stop高(高値)]が[1]と[同じ]でない場合 //2.1) [Stop安(安値)]が[1]と[同じ]場合、[当日指定値][安値(+1Tick)]で手仕舞いする //2.2) [Stop安(安値)]が[1]と[異なる]場合、[当日引け]で手仕舞いする codes = CodeList if ($code_num && $code_num != Length(codes)) Print("前回と異なる銘柄リストでは実行できません。") Dummy end $code_num = Length(codes) //グローバル変数を初期化 if (!$__INIT__) $budgetIni = 10000000 $buyUnit = 1000000 // 1回の購入資金 (100万円) $MaxHoldDay = 0 // 最大保有日数 $shortSelling = 1 // 空売り戦略 Yes(1)/No(0) $Interest = 1 // 無制限(0) / 単利(1) / 複利(2) $reverse = 0 // 購入順序 昇順(0) / 降順(1) $udcount = 1 // 騰落レシオ利用数 Init() // テクニカル指標初期化 -------------------------- $ratiodate[0] = 3 // 騰落レシオ日数 //------------------------------------------------ InitDone() // 騰落レシオ初期化 $__INIT__ = 1 end def Main(i) //================================================== // 条件(買条件, 売条件共通部分) //================================================== //まだ上場していない銘柄は株価データがないためnullが返る if (Index == null) return end if ! ($order[(int)Code]) $order[(int)Code] = i end if ! (Index > 75) return end //================================================== // 保有してない→購入 //================================================== if (! $hold[i]) //================================================== // 売買(買い) //================================================== // 1) 株価の低い場合はランキングしない[150]万円以下 // 2) 売買代金の少ない場合はランキングしない(売買代金の[3]日間平均が[5]千万円以下の場合) if ! (Volume && Close && {-1}Close && {-2}Close && {-3}Close && {-4}Close && {-5}Close && SalesValue() > 1000) return end // 1) [ランキング条件]の中で[5日間の前日比(率)]が最小から[5]つ抽出 day1 = (float)(Close - {-1}Close) / {-1}Close * 100 day2 = (float)({-1}Close - {-2}Close) / {-2}Close * 100 day3 = (float)({-2}Close - {-3}Close) / {-3}Close * 100 day4 = (float)({-3}Close - {-4}Close) / {-4}Close * 100 day5 = (float)({-4}Close - {-5}Close) / {-5}Close * 100 //2) 東証1部騰落レシオ(3)が[100]より[小さい] if (100 > $ratio[0]) //) [翌日始値]が[終値(+10.00%)]より[大きい] if ({1}Open > Close * 1.1) //3) [翌日逆指値(終日)][翌日始値(-1Tick)]で[売り]を仕掛ける $buyflag[i][0] = 1 // 好きなパラメータをもとにソート $buyflag[i][1] = day1 + day2 + day3 + day4 + day5 $buyCnt = $buyCnt + 1 else //2) [翌日指値寄付]が、終値(-2.50%)で[売り]を仕掛ける $buyflag[i][0] = 2 // 好きなパラメータをもとにソート $buyflag[i][1] = day1 + day2 + day3 + day4 + day5 $buyCnt = $buyCnt + 1 end end //================================================== // 保有している→売却 //================================================== elsif ($hold[i]) if ($set[i] < 1) $set[i] = 1 return end $set[i] = $set[i] + 1 //================================================== // 売買(売り) //================================================== // 1) [Stop高(高値)]が[1]と[同じ] check = High >= Close + DailyPriceLimit(Close) if (check) // 2) [当日指定値][高値]で手仕舞いする PrintLog("手仕舞い1") $sellflag[i] = 1 $set[i] = 0 // 2) [Stop高(高値)]が[1]と[同じ]でない場合 else // 2.1) [Stop安(安値)]が[1]と[同じ]場合 check = Close - DailyPriceLimit(Close) >= Low if ($set[i] >= $MaxHoldDay) //3) [当日指定値][安値(+1Tick)]で手仕舞いする PrintLog("手仕舞い2") $sellflag[i] = 2 $set[i] = 0 else //2) [当日引け]で手仕舞いする PrintLog("手仕舞い3") $sellflag[i] = 3 $set[i] = 0 end end end end //================================================== // [買い]を仕掛ける //================================================== def BuyingLimitedPrice2(i, d, t) //資金が不足している場合は何もしない if ($long == 0) return end //予算を超えない場合だけ買う if ($long * t <= $budget) if ($Interest == 1 || $Interest == 2) $budget = $budget - $long * t end $hold[i] = $long $buy[i] = t if ($shortSelling) {d}Sell((int)t, $hold[i]) else {d}Buy((int)t, $hold[i]) end Print("B 予算残り = " + $budget) $set[i] = 0 else PrintLog("予算を超過しています") end end //================================================== // 購入可能かチェック //================================================== def CheckHighLow2(t) if ! ({1}High > t && t > {1}Low) return 0 end if ($shortSelling) // [売り] 翌日始値が指値以上なら約定 if ! ({1}Open >= t) return 0 end else // [買い] 翌日始値が指値以下なら約定 if ! (t >= {1}Open) return 0 end end return t end //================================================== // [翌日逆指値(終日)][終値(-1Tick)] //================================================== def StopOrderCloseTick2() t = Close - Yobine(Close, 0) return CheckHighLow2(t) end //================================================== // [翌日指値(寄付)][終値(num%)] //================================================== def StopOrderClose2(num) t = Close * num return CheckHighLow2(t) end //================================================== // 買い(カスタマイズ条件) //================================================== def Buying2(i) if (0 == PricedataExistCheck({1}Open)) if ($buyflag[i][0] == 1) //3) [翌日逆指値(終日)][翌日始値(-1Tick)]で[売り]を仕掛ける t = StopOrderCloseTick2() elsif ($buyflag[i][0] == 2) //2) [翌日指値寄付]が、終値(-2.50%)で[売り]を仕掛ける t = StopOrderClose2(0.975) end if (t) BuyingLimitedPrice2(i,1,t) end end end //==================== // 買い処理 //==================== def SortBuy(i) if (PricedataExistCheck(Close)) return end $long = 0 $long = Num($buyUnit, Close) codeset = $order[(int)Code] Buying2(codeset) end //================================================== // [売り]を仕掛ける //================================================== def SellingLimitedPrice2(i, d, t) if ($shortSelling) {d}Buy(t, $hold[i]) else {d}Sell(t, $hold[i]) end if ($Interest == 2) $budget = $budget + t * $hold[i] elsif ($Interest == 1) $budget = $budget + $buy[i] * $hold[i] end $hold[i] = 0 Print("S 予算残り = " + $budget) end //================================================== // 売り(カスタマイズ条件) //================================================== def Selling2(i) if ($sellflag[i] == 1) // 2) [当日指定値][高値]で手仕舞いする if (0 == PricedataExistCheck(High)) SellingLimitedPrice2(i, 0, High) end elsif ($sellflag[i] == 2) // 3) [当日指定値][安値(+1Tick)]で手仕舞いする if (0 == PricedataExistCheck(Low)) SellingLimitedPrice2(i, 0, Low + Yobine(Low, 0)) end elsif ($sellflag[i] == 3) // 4) [当日引け]で手仕舞いする SellingClose(i,0) end end //==================== // 売り処理 //==================== def Sell_(i) if ($sellflag[i]) Selling2(i) $sellflag[i] = 0 end // 使用した$buyflag 配列を初期化 if ($buyflag[i][0]) $buyflag[i][0] = 0 $buyflag[i][1] = 0 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) // while i + 1 < $buyCnt while i + 1 < 5 i = i + 1 {$sortList2[i]}SortBuy(i) end end i = -1 while i + 1 < $code_num i = i + 1 {codes[i]}Sell_(i) end |
実装は、1日経過したら手仕舞いするように一部変更しています。
バックテスト結果
計算時間は約7時間です。
【追記】銘柄ソートが遅いようなので、あらかじめ購入予定の銘柄を閾値で絞り込むと、誤差一割未満で計算時間を1時間以下にできました。
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 |
株価データ: 日足 銘柄リスト: 借貸(東一)20190805 1998/01/05~2019/09/13における成績です。 ---------------------------------------- 全トレード数 3028 勝ちトレード数(勝率) 2139(70.64%) 負けトレード数(負率) 889(29.36%) 全トレード平均利率 1.58% 勝ちトレード平均利率 2.85% 負けトレード平均損率 -1.47% 勝ちトレード最大利率 25.15% 負けトレード最大損率 -15.92% 全トレード平均期間 1.50 勝ちトレード平均期間 1.47 負けトレード平均期間 1.57 ---------------------------------------- 必要資金 ¥3,765,400 最大ポジション(簿価) ¥4,745,900 最大ポジション(時価) ¥5,646,900 純利益 ¥43,081,600 勝ちトレード総利益 ¥54,857,800 負けトレード総損失 -¥11,776,200 全トレード平均利益 ¥14,228 勝ちトレード平均利益 ¥25,646 負けトレード平均損失 -¥13,247 勝ちトレード最大利益 ¥239,200 負けトレード最大損失 -¥150,000 プロフィットファクター 4.66 最大ドローダウン(簿価) -¥520,600 最大ドローダウン(時価) -¥459,500 ---------------------------------------- 現在進行中のトレード数 0 ---------------------------------------- 平均年利 57.21% 平均年利(直近5年) 33.47% 最大連勝 18回 最大連敗 5回 ---------------------------------------- [年度別レポート] 年度 取引回数 運用損益 年利 勝率 PF 最大DD 2019年 82回 ¥537,600円 14.28% 70.73% 2.91倍 -3.97% 2018年 107回 ¥1,527,800円 40.57% 85.05% 10.75倍 -2.66% 2017年 49回 ¥405,200円 10.76% 69.39% 3.39倍 -2.39% 2016年 163回 ¥2,427,900円 64.48% 73.62% 7.36倍 -3.69% 2015年 129回 ¥1,402,900円 37.26% 68.22% 3.39倍 -15.92% 2014年 76回 ¥697,500円 18.52% 63.16% 3.65倍 -2.67% 2013年 167回 ¥2,445,300円 64.94% 68.86% 3.72倍 -8.83% 2012年 63回 ¥599,600円 15.92% 77.78% 3.97倍 -8.62% 2011年 87回 ¥854,700円 22.70% 73.56% 2.86倍 -7.27% 2010年 95回 ¥1,174,400円 31.19% 75.79% 6.31倍 -3.45% 2009年 163回 ¥1,980,400円 52.59% 68.71% 4.08倍 -10.56% 2008年 326回 ¥6,248,000円 165.93% 72.70% 3.82倍 -14.63% 2007年 150回 ¥2,510,900円 66.68% 75.33% 6.12倍 -7.33% 2006年 175回 ¥3,221,100円 85.54% 72.57% 5.89倍 -6.16% 2005年 70回 ¥646,700円 17.17% 68.57% 2.68倍 -10.72% 2004年 135回 ¥2,667,100円 70.83% 77.04% 8.69倍 -4.52% 2003年 219回 ¥3,514,400円 93.33% 79.00% 5.65倍 -6.55% 2002年 260回 ¥3,610,400円 95.88% 70.77% 4.69倍 -4.43% 2001年 278回 ¥4,333,100円 115.08% 78.06% 6.74倍 -5.15% 2000年 234回 ¥2,276,600円 60.46% 70.94% 3.47倍 -6.53% |
利益曲線は次のとおりです。
凄い結果になりました。
また、レアキャラを見つけました!!!!
兀突骨(ごつとつこつ)
武力も知力も呂布相当or以下・・・だって役に立たないから・・・。
因みに正史には登場せず、演義の架空キャラのようです。
ソースコードの調査結果、いくつもの誤実装がありました。
手法を忠実に実装していない・・・のは問題ではないです。
間違い箇所は面倒なので書きません。見て調査出来ない人はprotra使えないと思うので。
まとめ
ネットに公開されているストラテジーは一通り実装したかと思ってます。
ただし、カーブが曲がらないストラテジーは見つかっていません。
あとは各著者のブログを漁りヒントを得たり、外部指標を取り込める仕組みをprotraに組み込むか・・・