今まで色々なテクニカル手法のバックテストを説明してきましたが、少し現実離れした売買のシミュレーションでした。
手法の有効性を検討するという点では問題ありませんが、次のような点が考慮されてないです。
- 同日の複数銘柄のシグナルからの買い選択
- 投資額を意識した売買
- 単元株を意識した売買
例えば、予算内でエントリーする銘柄を決めて、単元数を意識した上でシミュレーションする必要があるはずです。
まずは、前回のprotra基礎編に目を通した上で見てください。
銘柄を横断するシステム
protraでは、工夫すれば次のようなシステムが実装可能です。
- 複数の銘柄で同日に発生したシグナルから、実際にエントリーするものを選ぶシステム
- すべての銘柄の投資額を計算して予算を超えていたらエントリーしないシステム
具体的なコード例としては「# loop-type: date-only」を先頭に付けるのがポイントです。
これにより、PtSimは保有しているすべての株価データのうち、一番古い日付から最新の日付まで一度だけシステムを実行します。
そのため、銘柄ごとに繰り返し実行する部分は自分で実装する必要があります。
「protraのマニュアル」と、サンプルの「MA Cross with CAP.pt」を確認すれば、何となく動作は理解できると思います。
「3点チャージ法」で試してみる
「3点チャージ手法」の内容は以前紹介済なので省略します。
まず「Charge3.pt」というファイル名で「Protra\system」のフォルダの下に次を保存します。
買いの優先順位は、DiffMAの値だけで比較しています。
個人的には、この後に正規化したり重み付けなどを行ってエントリーする銘柄の最適な選択が必要だと思います。
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 |
# loop-type: date-only // 3点チャージ投資法 require "TIlib" require "Nehori" // グローバル変数を初期化 if !$__INIT__ $MHP = 10 // 最大保有日 $BUDGET = 1000000 // 投資総額 $ISCOMPO = 0 // 利益を投資に回す 1:Yes // 銘柄の数だけグローバル変数を用意する $Diff = [Length(CodeList)] $VR = [Length(CodeList)] $RSI = [Length(CodeList)] $__INIT__ = 1 end // TIlibのオブジェクトを生成 def CreateObject(i) $Diff[i] = DiffMA_new(26) $VR[i] = VR_new(25, 0) $RSI[i] = RSI_new(14, 0) end // 指標の計算を一日進める def NextObject(i) DiffMA_next($Diff[i]) VR_next($VR[i]) RSI_next($RSI[i]) end // 買い条件を定義 def BuyCond(i) diff = DiffMA_value($Diff[i]) vr = VR_value($VR[i]) rsi = RSI_value($RSI[i]) if ! (diff && vr && rsi) return end if diff <= -15 && vr <= 70 && rsi <= 25 return diff * -1 end end // 売り条件を定義 def SellCond(i) if ! Close return end return Close >= 1.10*$buy || Close <= 0.85*$buy end Main2() |
次に「Nehori.pt」というファイル名で「Protra\lib」のフォルダの下に次を保存します。
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 |
// 最大保有数の判定 def HoldingPeriod () if $set <= 0 //0以下でも売り条件(期限切れ) return 1 end $set = $set - 1 //1日1回カウンタ減らしておく return end // 単元株数を考慮して予算内の購入数を返す def Num2(price) unit = Unit2(price) return ($BUDGET / (unit * price)) * unit end // 買いルールの共通処理 def WrapBuyCond(i) if Index == null // まだ上場していない return end if ! $FLAG[i] || $FLAG[i] == 1 return end return BuyCond(i) end // 最大値を返す def CheckMaxStock() i = 0 condid = 0 id = null // 文字列型at作用素を与えて実行する while i < Length(CodeList) value = {CodeList[i]}WrapBuyCond(i) if value && condid < value condid = value id = CodeList[i] end i = i + 1 end return id end def WrapNextObject(i) if Index == null // まだ上場していない return end if ! $FLAG[i] || $FLAG[i] == 1 return end NextObject(i) end def WrapCreateObject(i) if Index == null // まだ上場していない return end if ! $FLAG[i] CreateObject(i) $FLAG[i] = 1 // return else $FLAG[i] = 2 end end // 同一日の買い銘柄数の選択 def Main2() if !$FLAG // 初期化 $FLAG = [Length(CodeList)] end // 文字列型at作用素を与えて実行する i = 0 while i < Length(CodeList) {CodeList[i]}WrapCreateObject(i) i = i + 1 end // 文字列型at作用素を与えて実行する i = 0 while i < Length(CodeList) {CodeList[i]}WrapNextObject(i) i = i + 1 end if ! $wait // 同日売買禁止 if $hold && $code && ({$code}SellCond($code) || {$code}HoldingPeriod) if {1}{$code}Open //翌日の始値で {1}{$code}Sell(Open, $hold) // 売る if $ISCOMPO // 利益を投資に回す場合 $BUDGET = $BUDGET + {1}{$code}Open * $hold end $wait = 2 else // 翌日の始値がないとき {$code}Sell(Close, $hold) // 便宜上終値で売る if $ISCOMPO // 利益を投資に回す場合 $BUDGET = $BUDGET + {$code}Close * $hold end $wait = 1 end $hold = 0 $code = null // Buy order elsif ! $hold $code = CheckMaxStock() // 購入銘柄 if $code if {1}{$code}Open $hold = {1}{$code}Num2(Open) // 購入数 if $hold == 0 // 買えない $code = null return end $buy = {1}{$code}Open // 買値 {1}{$code}Buy(Open, $hold) // 買う if $ISCOMPO // 利益を投資に回す場合 $BUDGET = $BUDGET - {1}{$code}Open * $hold end $set = $MHP $wait = 2 end else end end else $wait = $wait - 1 // $waitが0となった後は売買 end end |
ソースコードは汚いです。
結果
平成10年の株価データを与えているのに、実際には平成12年からシミュレーションを始めるようです・・・なぜだろう?
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 |
株価データ: 日足 銘柄リスト: 日経225採用銘柄 10/01/05~29/05/26における成績です。 ---------------------------------------- 全トレード数 182 勝ちトレード数(勝率) 90(49.45%) 負けトレード数(負率) 92(50.55%) 全トレード平均利率 1.18% 勝ちトレード平均利率 13.11% 負けトレード平均損率 -10.50% 勝ちトレード最大利率 72.92% 負けトレード最大損率 -39.84% 全トレード平均期間 14.08 勝ちトレード平均期間 12.61 負けトレード平均期間 15.51 ---------------------------------------- 必要資金 ¥1,008,200 最大ポジション(簿価) ¥1,000,000 最大ポジション(時価) ¥2,059,200 純利益 ¥2,230,700 勝ちトレード総利益 ¥10,964,400 負けトレード総損失 -¥8,733,700 全トレード平均利益 ¥12,257 勝ちトレード平均利益 ¥121,827 負けトレード平均損失 -¥94,932 勝ちトレード最大利益 ¥728,000 負けトレード最大損失 -¥388,800 プロフィットファクター 1.26 最大ドローダウン(簿価) -¥1,234,900 最大ドローダウン(時価) -¥1,234,900 ---------------------------------------- 現在進行中のトレード数 1 |
利益曲線は次のとおりです。
17年間(平成12年~)で売買取引可能日は200日×17年の3400日です。
平均保有期間が14日であれば、買いのタイミング回数は最大で242回しかありません。
毎日 買いシグナルが出るはず無いので、全トレード数が182回は妥当な数値です
結果的に、バックテストで17年間で100万円が223万円(+123万円)になりました。
要するに年間利益7万円です・・・。
ようやく知った現実値・・寂しすぎる
※ プロフィットファクターが「1.26」なので元々分かっていた事実ですが・・・
その場合は、利益分を加えて再投資すれば最終利益は上がるはず!!
「ISCOMPO = 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 |
株価データ: 日足 銘柄リスト: 日経225採用銘柄 10/01/05~29/05/26における成績です。 ---------------------------------------- 全トレード数 229 勝ちトレード数(勝率) 98(42.79%) 負けトレード数(負率) 131(57.21%) 全トレード平均利率 0.99% 勝ちトレード平均利率 12.93% 負けトレード平均損率 -7.94% 勝ちトレード最大利率 86.79% 負けトレード最大損率 -28.33% 全トレード平均期間 10.18 勝ちトレード平均期間 11.72 負けトレード平均期間 9.03 ---------------------------------------- 必要資金 \999,900 最大ポジション(簿価) \2,240,000 最大ポジション(時価) \2,360,000 純利益 \890,500 勝ちトレード総利益 \13,662,300 負けトレード総損失 -\12,771,800 全トレード平均利益 \3,889 勝ちトレード平均利益 \139,411 負けトレード平均損失 -\97,495 勝ちトレード最大利益 \579,600 負けトレード最大損失 -\424,000 プロフィットファクター 1.07 最大ドローダウン(簿価) -\1,635,800 最大ドローダウン(時価) -\1,681,100 ---------------------------------------- 現在進行中のトレード数 1 |
利益曲線は次のとおりです。
あれれ・・なぜか利益が減りました・・。
その他考慮したい点は「手数料」「税率20%」「トレイリングストップ」「OCO注文」などです。
バックテストを現実にできる限り近付ければ、実売買してみても良いかなぁ・・・。
まだ「聖杯」が見つかってませんが・・・