売買ルールにトレンド判定を盛り込む方法を考えます。
Utilityの関数化と同様に、外部に出して汎用的なコードにします。
・投資予算に制限を加える
・共通コードを関数化して可読性を向上させる その2
・共通コードを関数化して可読性を向上させる その3
・本ブログの内容において、正当性を保証するものではありません。
・本ブログを利用して損失を被った場合でも一切の責任を負いません。
・最終的な決定は、ご自身の判断(自己責任)でお願い致します。
トレンド判定
検証に使用した売買ルールは、以下の逆張り手法です。
◆買い:以下を満たしたとき、翌日の始値が買う
・終値と移動平均(5日)との乖離率が-7%以下
◆売り:以下のいずれかを満たしたとき、翌日の始値で売る
・終値と移動平均(5日)との乖離率が0%以上
・購入から10日経過
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 |
#loop-type: date-only #================================================== # 逆張りテスト.pt #-------------------------------------------------- # このシステムのルール # # <買い条件> # ・終値と移動平均(5日)との乖離率が-7%以下 # を満たしたとき、翌日の始値で買う # # <売り条件> #・終値と移動平均(5日)との乖離率が0%以上 #・購入から10日経過 # のいずれか満たしたとき、翌日の始値で売る #-------------------------------------------------- # written by グコウ, 2018/8/15 #================================================== require "TIlib" require "Utility" codes = CodeList if $code_num && $code_num != Length(codes) Print("前回と異なる銘柄リストでは実行できません。") Dummy end $code_num = Length(codes) #グローバル変数を初期化 if ! $__INIT__ $budgetIni = 10000000 #投資総額 (1000万円) $budget = $budgetIni $buyUnit = 1000000 #1回の購入資金 (100万円) $MaxHoldDay = 10 #最大保有日数 $Interest = 1 #無制限(0) / 単利(1) / 複利(2) #-------------------------------------------- $BB5 = [$code_num] $set = [$code_num] $buy = [$code_num] $hold = [$code_num] $__INIT__ = 1 end def Main(i) #================================================== # 条件(買条件, 売条件共通部分) #================================================== #まだ上場していない銘柄は株価データがないためnullが返る if Index == null return end if ! $BB5[i] #Tilibのオブジェクト生成 $BB5[i] = BB_new(5) #銘柄ごとのグローバル変数を初期化する $hold[i]=0 return end #指標の計算を1日進める BB_next($BB5[i]) ma5 = BB_value($BB5[i]) #指標の計算に必要な日数を経過していない場合は何もしない if ! ma5 return end #終値と5日移動平均線の乖離率を計算する r5 = 100*(Close - ma5)/ma5 #================================================== # 条件1 #================================================== if 1==PricedataExistCheck(Close) return end #エントリーの条件を判定 if (! $hold[i] && r5 <= -7) #================================================== # 売買(買い) #================================================== $long = 0 $long = Num($buyUnit,Close) if 0==PricedataExistCheck({1}Open) BuyingOpen(i,1) else if 1==PricedataExistCheck({2}Open) BuyingClose(i,0) else BuyingOpen(i,2) end end #================================================== # 条件2 #================================================== elsif $hold[i] if 1==PricedataExistCheck(Close) return end if $set[i] < 1 $set[i] = $set[i] + 1 return end $set[i] = $set[i] + 1 if (r5>0 || $set[i] > $MaxHoldDay) #================================================== # 売買(売り) #================================================== if 0==PricedataExistCheck({1}Open) SellingOpen(i,1) else if 1==PricedataExistCheck({2}Open) SellingClose(i,0) else SellingOpen(i,2) end end end end end //==================== // 銘柄コードを変えながらMain関数を実行 //==================== i = -1 while i + 1 < $code_num i = i + 1 {codes[i]}Main(i) // 文字列型at作用素を与えて実行する。 end |
トレンド判定にはいくつか手法がありますが、今回は「株価位置」を使用します。
過去 x日の最高値,最安値に対して、現在の株価がどの程度の位置にあるかを確認します。株価位置のイメージは以下の通り。
例えば、「現在の株価が最高値,最安値の中間値より大きい場合、現在その株価は上昇トレンドにある」と判断します。
「株価位置」を実装する
「株価が上昇傾向にあるときに購入」を実装していきます。
「【Protra】共通コードを関数化して可読性を向上させる」のUtility.ptと同じく、トレンド判定ルールについても、 Protra\libに以下のコードをTrendCheck.ptを作成しました。
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 |
#================================================== # 株価位置 #================================================== def StockPosition(i) if ! $__INITSP__ $HL = [$code_num] $__INITSP__ = 1 end if ! $HL[i] #Tilibのオブジェクト生成 stockPositionDay = 75 $HL[i] = HighLow_new(stockPositionDay) return 0 end #指標の計算を1日進める HighLow_next($HL[i]) highest = HighLow_high($HL[i]) lowest = HighLow_low($HL[i]) if !highest || !lowest return 0 end # 過去75日の最大、最小値の中間価を算出 threshold = lowest + (highest-lowest)/100 * 50 # 当日の株価位置がしきい値より大きければ1を返す return Close > threshold end |
Tilib のHighLowを使用しています。やっていることは単純で、過去 75日の最高値と最安値を検索しているだけです。
27行目でしきい値を計算。ここでは、最高値と最安値の中間価をしきい値としています。
最終的に30行目で、当日の終値がしきい値より大きければ、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 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 |
#loop-type: date-only #================================================== # 株価位置テスト.pt #-------------------------------------------------- # このシステムのルール # # <買い条件> # ・終値と移動平均(5日)との乖離率が-7%以下 # を満たしたとき、翌日の始値で買う # # <売り条件> #・終値と移動平均(5日)との乖離率が0%以上 #・購入から10日経過 # のいずれかを満たしたとき、翌日の始値で売る #-------------------------------------------------- # written by グコウ, 2018/8/16 #================================================== require "TIlib" require "Utility" require "TrendCheck" 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 = 10 #最大保有日数 $Interest = 0 #無制限(0) / 単利(1) / 複利(2) #------------------------------------------------ $set = [$code_num] $buy = [$code_num] $hold = [$code_num] #------------------------------------------------ $BB5 = [$code_num] $__INIT__ = 1 end def Main(i) #================================================== # 条件(買条件, 売条件共通部分) #================================================== #まだ上場していない銘柄は株価データがないためnullが返る if Index == null return end if ! $BB5[i] #Tilibのオブジェクト生成 $BB5[i] = BB_new(5) #銘柄ごとのグローバル変数を初期化する $hold[i]=0 return end #指標の計算を1日進める BB_next($BB5[i]) ma5 = BB_value($BB5[i]) #================================================= #トレンド判定 #================================================= stpflg = 0 if 75 < Index stpflg = StockPosition(i) end #指標の計算に必要な日数を経過していない場合は何もしない if ! ma5 return end #終値と5日移動平均線の乖離率を計算する r5 = 100*(Close - ma5)/ma5 #================================================== # 条件1 #================================================== if 1==PricedataExistCheck(Close) return end #エントリーの条件を判定 if (! $hold[i] && r5 <= -7 && stpflg == 1 ) #================================================== # 売買(買い) #================================================== $long = 0 $long = Num($buyUnit,Close) if 0==PricedataExistCheck({1}Open) BuyingOpen(i,1) else if 1==PricedataExistCheck({2}Open) BuyingClose(i,0) else BuyingOpen(i,2) end end #================================================== # 条件2 #================================================== elsif $hold[i] if 1==PricedataExistCheck(Close) return end if $set[i] < 1 $set[i] = $set[i] + 1 return end $set[i] = $set[i] + 1 if (r5>0 || $set[i] > $MaxHoldDay) #================================================== # 売買(売り) #================================================== if 0==PricedataExistCheck({1}Open) SellingOpen(i,1) else if 1==PricedataExistCheck({2}Open) SellingClose(i,0) else SellingOpen(i,2) end end end end end //==================== // 銘柄コードを変えながらMain関数を実行 //==================== i = -1 while i + 1 < $code_num i = i + 1 {codes[i]}Main(i) // 文字列型at作用素を与えて実行する。 end |
20行目で、「TrendCheck」をインポートしています。
67-73行目でトレンド判定。stpflgという変数でフラグ管理しています。これは他の判定条件を追加したときに、一律にstpflgを使用することを見越してです。
71行目、「75日< 上場からの期間」 としているのは、過去日数を参照するときに上場から75日後でないと、最高値,最安値が計算されないためです。
90行目の買い条件にstpflgを追加。 なお、この売買ルールでは買い条件にのみトレンド判定を使用しています。
過去株価の参照に時間を要するため、実行時間は大幅に伸びる点に注意です。
効果の検証
トレンド判定の効果を検証します。予算は無制限、対象銘柄は売上上位500銘柄とします。
はじめに、トレンド判定なし。
続いて、「当日の終値が、過去75日の最高値と最安値の中間値より高い場合、上昇トレンドと判断」を盛り込んだ場合です。
条件が厳しくなる分トレード数は減少し、それに伴い純利益も減少します。
一方で、ドローダウンが大きく緩和されていることがわかります。ただ勝敗率はあまり変わりないようです。つまりトレンド判定を導入したことで「大きく下落する株価」を避けることができています。