【前回のあらすじ】
おっす!オラ悟空!
みんなはドローダウン(時価)って知ってっか?
何でも含み損を計測するすげぇ値なんだと
次はそのドローダウン(時価)、見れるかもしれねぇぞ
じっちゃん、protraに追加実装できたら、その値を見せてやるって言うんだ
追加実装って何だ?
次回、『ドローダウン(時価)の追加実装』
みんな見てくれよな!
【結果】
何も実現できず・・・・・
【実は勘違いされているアニメの名言雑学ランキング】
1位 「オッス!オラ悟空」は本編では一度も言ってない
2位 ケンシロウ「おまえはもう死んでいる」は、原作では一度しか言ってない
3位 「アムロ、行きまーす」は、一回しか言ってない
3連休でProtra本体をイジったり、デスクトップパソコンでProtraを動かしたりしてみましたが、どれも気に入る結果が得られませんでした。
さらに、週に10回程度シグナルが出てもおかしくない手法なのに、8月に入ってシグナルが一切出ておらず何も仕込みができません。
Protraで最大ドローダウン(時価)を計算してみる
「システムトレードの達人」に記載されている値をProtraで実現しようと試みました。
しかし「初期の運用資産」を、売買スクリプト側で勝手に決められる仕様のため、Protra側では幾らで取引しているのか判断できません。
そのため、
利回り ○%
最大DD(簿価)の割合(日付)
最大DD(時価)の割合(日付)
などを表現することができません。
苦肉の策で次のようにしました。
こちらコードは公開しますが・・・
「空売り」の判定未実装&Protraの標準出力DDと値が異なる事があるので使わない方が懸命です。
コードもよく分からなくなってきました・・・・。
で、何故か成績計算を数回繰り返したら最大ドローダウン(簿価)が9%だった手法が、11%までドローダウンが落ちてしまいました・・・。理由不明。
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 |
--- Performance.cs 2019-08-12 08:00:41.890930000 +0900 +++ Performance.cs 2019-08-12 08:22:21.691202400 +0900 @@ -20,6 +20,7 @@ using System; using System.ComponentModel; +using System.Collections.Generic; using Protra.Lib.Config; using Protra.Lib.Data; using Protra.Lib.Lang.Builtins; @@ -47,6 +48,14 @@ private float _bookMaxPosition; // 時価の最大ポジション private float _marketMaxPosition; // 簿価の最大ポジション private float _totalProfit; // 総利益 + private Dictionary<int, float> _allTradesYear; // 各年のトレード数 + private Dictionary<int, float> _totalProfitYear; // 各年の総利益 + private Dictionary<int, float> _totalWinTradesYear; // 各年の勝率 + private Dictionary<int, float> _totalMaxDrowDownYear; // 各年の最大ドローダウン + private Dictionary<int, float> _totalMaxMarketDrowDownYear; // 各年の時価最大ドローダウン + private Dictionary<int, float> _totalWinMaxProfitYear; // 各年の勝ちトレード最大利益 + private Dictionary<int, float> _totalLoseMaxProfitYear; // 各年の負けトレード最大損失 + private Dictionary<int, DateTime> _maxMarketDrowDawnDate; // Max時価DDのトレードの日付 private float _winTotalProfit; // 勝ちトレード総利益 private float _winMaxProfit; // 勝ちトレード最大利益 private float _loseMaxLoss; // 負けトレード最大損失 @@ -67,6 +76,14 @@ _name = name; _brandList = brandList; _timeFrame = timeFrame; + _allTradesYear = new Dictionary<int, float>(); + _totalProfitYear = new Dictionary<int, float>(); + _totalWinTradesYear = new Dictionary<int, float>(); + _totalMaxDrowDownYear = new Dictionary<int, float>(); + _totalMaxMarketDrowDownYear = new Dictionary<int, float>(); + _totalWinMaxProfitYear = new Dictionary<int, float>(); + _totalLoseMaxProfitYear = new Dictionary<int, float>(); + _maxMarketDrowDawnDate = new Dictionary<int, DateTime>(); } /// @@ -183,7 +200,7 @@ realTotalBuy -= (totalBuy = (float)position * log.Price); else if (position < 0) realTotalSell -= (totalSell = (float)-position * log.Price); - EvaluateTrade(log.Order == Order.Sell, (log.Date - startDate).Days, realTotalBuy, realTotalSell); + EvaluateTrade(log.Order == Order.Sell, (log.Date - startDate).Days, realTotalBuy, realTotalSell, log.Date, dailyProfit); } if (position != 0) _runningTrades++; @@ -198,14 +215,68 @@ return realProfits; } - private void EvaluateTrade(bool isLong, int term, float totalBuy, float totalSell) + private void EvaluateTrade(bool isLong, int term, float totalBuy, float totalSell, DateTime date, PricePair dailyprofit) { + var year = date.Year; _allTrades++; var ratio = isLong ? totalSell / totalBuy - 1 : 1 - totalBuy / totalSell; // 空売りは売りポジションが分母 _allProfitRatio += ratio; _allTerm += term; var profit = totalSell - totalBuy; _totalProfit += profit; + // 年度別のトータル資金 + if (_totalProfitYear.ContainsKey(year) == true) + { + _totalProfitYear[year] += profit; + _allTradesYear[year]++; + if (profit >= 0) + { + _totalWinTradesYear[year]++; + _totalWinMaxProfitYear[year] += profit; + } + else + { + _totalLoseMaxProfitYear[year] += profit; + } + if (totalSell < totalBuy) // 負け + { + _totalMaxDrowDownYear[year] = Math.Min(_totalMaxDrowDownYear[year], ratio); + } + if (_totalMaxMarketDrowDownYear[year] > dailyprofit.Market) + { + _totalMaxMarketDrowDownYear[year] = dailyprofit.Market; + _maxMarketDrowDawnDate[year] = date; + } + } + else + { + _totalProfitYear.Add(year, profit); + _allTradesYear.Add(year, 1); + if (profit >= 0) + { + _totalWinTradesYear.Add(year, 1); + _totalWinMaxProfitYear.Add(year, profit); + _totalLoseMaxProfitYear.Add(year, 0); + } + else + { + _totalWinTradesYear.Add(year, 0); + _totalWinMaxProfitYear.Add(year, 0); + _totalLoseMaxProfitYear.Add(year, profit); + } + if (totalSell < totalBuy) // 負け + { + _totalMaxDrowDownYear.Add(year, ratio); + _totalMaxMarketDrowDownYear.Add(year, dailyprofit.Market); + _maxMarketDrowDawnDate[year] = date; + } + else + { + _totalMaxDrowDownYear.Add(year, 0); + _totalMaxMarketDrowDownYear.Add(year, 0); + _maxMarketDrowDawnDate[year] = date; + } + } if (totalSell > totalBuy) // 勝ち { _winTrades++; @@ -314,6 +385,24 @@ _winTotalProfit / -loseTotalLoss, _bookMaxDrowDown, _marketMaxDrowDown, _runningTrades)); + appendText(string.Format( + "----------------------------------------\n" + + "[年度別レポート]\n")); + // Dictionaryの内容をコピーして、List + List<KeyValuePair<int, float>> list = new List<KeyValuePair<int, float>>(_allTradesYear); + list.Sort((a, b) => a.Key - b.Key); //昇順 + appendText(string.Format("年度\t取引回数\t運用損益\t勝率\tPF\t最大DD\t最大DD(時価)\n")); + foreach (KeyValuePair<int, float> pair in list) + { + appendText(string.Format( + "{0}年\t{1}回\t\t{2:c}円\t{3:p}\t{4:n}倍\t{5:p}\t{6:c}円({7})\n", + pair.Key, pair.Value, _totalProfitYear[pair.Key], + _totalWinTradesYear[pair.Key] / pair.Value, + Math.Abs(_totalWinMaxProfitYear[pair.Key] / _totalLoseMaxProfitYear[pair.Key]), + _totalMaxDrowDownYear[pair.Key], _totalMaxMarketDrowDownYear[pair.Key], + _maxMarketDrowDawnDate[pair.Key].ToString("yyyy/MM/dd") + )); + } } } -} \ No newline at end of file +} |
で、計算してみたは良いけど・・・・
借貸銘柄を8月5日分に変更すると、世紀東急工業(1898)が2011年の大震災でストップ高→下落→ストップ高となり、-21.43%の下落となりました。
で、MAXドローダウンの時価は40%でした。。100万円投資で40万円の損失に耐えれるか・・・。。
デスクトップパソコンの速度が遅すぎる
アメリカで購入したLenovoのWindowsパソコン(CPU:Core-i5-4430 3.00GHz、RAM:12GB)を使って、バックテストを実施すると5時間かかりました。
一方、ノートパソコン(Core-i5-6200 CPU 2.30GHz、RAM 8.00GB)では、2時間以内で計算終了します。
この差は一体何なのでしょうか?
ノートパソコンのCPU負荷は33%程度ありました。デスクトップパソコンのCPU負荷を確認すると・・・・。
すっごい涼しい顔で処理し過ぎでしょ・・・。
マルチコアのCPUを使っているのに活かし切れていないのでは?と調査したところ、.NETのGCのモードをサーバーGCというものに変更すると解決するらしいと書いてありました。
が、これは役に立たず・・・・・
具体的には、App.configにgcServerという要素を追加してenabled属性の値をtrueにします。
1 2 3 4 5 6 7 8 9 10 |
xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /> </startup> <runtime> <gcConcurrent enabled="false"/> <gcServer enabled="true"/> </runtime> </configuration> |
つまり、何もできてませーん・・・・。
SBI証券のバックアップサイトの仕様が変わる
SBIのバックアップサイトの仕様が変わって、従来のライブラリでは注文失敗するらしい。
・・・対応検討面倒だな。
とっぴんぱらりのぷ~。