はっきり言って、私のサイトで「システムトレードの記事」が全く人気がありません。
ここから、多くの投資家が「システムトレードは勝てない」と考えているのでしょう。
さらに「protra」というツール使ったシステムトレードを検討している人なんて、日本に100人程度しかいないと思ってます。
そもそも「テクニカル指標をこねくり回して勝てる手法を見つける」というやり方自体が10年前の流行です。
「日足を使った翌日の寄付きでの売買」なんて、もはや化石
じゃぁ、なぜやっているのか・・・って?
まだ、そこに未来があると信じているからです。
昨年、外資系ファンドに転職した先輩がいます。
彼は、10億トレーダー達の英知を学びつつ最先端の自動売買研究をしています。
私との給料の年収は10倍違います。
英知の一つでも拝借しようかと思い、私の行っているシステムトレードの内容を伝えたところ、ありがたいことにメールの返信を頂きました。
テクニカル指標を使うのは、機械学習アプローチならわりとメジャーなやり方だと思っています。
日々変化するものはそれくらいしかないですから。ただ、やったらわかりますけど世の中甘くないです。
あと君の場合だと、休みの日の労力をこれに使うよりも、会社で昇進できるように全力を尽くした方がリターンがよいと思いますけどね。
はい終了。
・・・3年の歳月を費やしているのです・・・。サンクコストの呪縛。
年毎の勝率、最大DD、PFを表示する
以前、「Protra使い方発展編(年毎の取引回数と総合利益を表示する)」という記事を公開しました。
Protra信者の中には、喜んで下さった方々がいました。
で、イザナミを見てみると、年毎の勝率、最大ドローダウン、プロフィットファクターなどが表示されており、欲しくなったのでProtraを修正しました。
修正したソースコード
組み込み関数等を調査する必要もなく、以前の実装に少し追加するだけで実現可能です。
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 |
--- Performance.cs 2019-06-29 16:12:04.954195100 +0900 +++ Performance.cs 2019-06-29 16:10:19.952856400 +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,12 @@ 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> _totalWinMaxProfitYear; // 各年の勝ちトレード最大利益 + private Dictionary<int, float> _totalLoseMaxProfitYear; // 各年の負けトレード最大損失 private float _winTotalProfit; // 勝ちトレード総利益 private float _winMaxProfit; // 勝ちトレード最大利益 private float _loseMaxLoss; // 負けトレード最大損失 @@ -67,6 +74,12 @@ _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>(); + _totalWinMaxProfitYear = new Dictionary<int, float>(); + _totalLoseMaxProfitYear = new Dictionary<int, float>(); } /// @@ -183,7 +196,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.Year); } if (position != 0) _runningTrades++; @@ -198,7 +211,7 @@ return realProfits; } - private void EvaluateTrade(bool isLong, int term, float totalBuy, float totalSell) + private void EvaluateTrade(bool isLong, int term, float totalBuy, float totalSell, int year) { _allTrades++; var ratio = isLong ? totalSell / totalBuy - 1 : 1 - totalBuy / totalSell; // 空売りは売りポジションが分母 @@ -206,6 +219,50 @@ _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); + } + } + 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); + } + else + { + _totalMaxDrowDownYear.Add(year, 0); + } + } if (totalSell > totalBuy) // 勝ち { _winTrades++; @@ -314,6 +371,23 @@ _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勝率\t最大DD\tPF\n")); + foreach (KeyValuePair<int, float> pair in list) + { + appendText(string.Format( + "{0}年\t{1}回\t\t{2:c}円\t{3:p}\t{4:p}\t{5:n}倍\n", + pair.Key, pair.Value, _totalProfitYear[pair.Key], + _totalWinTradesYear[pair.Key] / pair.Value, + _totalMaxDrowDownYear[pair.Key], + Math.Abs(_totalWinMaxProfitYear[pair.Key] / _totalLoseMaxProfitYear[pair.Key]))); + } + } } } |
実際の画面はこんな感じです。
年度別で細かい値を気にするようになってきたということは、勝率やPFの高い手法が見つかり始めた証拠かも知れません。
てか、イザナミだと「株システムトレードストラテジー通販サイト」があるっぽいし、3年間 私は一体何をしているのでしょうか・・・。