PLOについての興味深い見解 - ページ 11 1...45678910111213 新しいコメント Andrey Khatimlianskii 2021.02.01 15:54 #101 Georgiy Merts:「神格化」については、fxsaber氏の表現がありますが、彼自身は「このコードは繰り返しテストされており、動作する」と述べるだけで、その仕組みについては言及しませんでした。それは、あってはならないことだと私は思います。このコードは、otfFilingType命令が実行 可能かどうかをチェックし、strSymbolで実行可能であればそれを返し、そうでなければ正解とするものです。 仕組みがまったくわからない。そして、fxsaberの権限にのみ依存すること。どなたか解説していただけませんか? それを理解するためには、この面倒な返り値を構成要素に分解すればよい。 Andrei Trukhanovich 2021.02.01 16:04 #102 Igor Makanu:"目的は手段を正当化する "の例ですね。 このコードはスパゲティみたいなものですが、おそらく今コドベースで最も有用な作家であり、私自身彼のコードをそのまま使っていることを考えると、他の人に批評してもらいましょう。 Igor Makanu 2021.02.01 16:27 #103 Andrei Trukhanovich:ちなみにこのコードはスパゲッティみたいなものですが、おそらく今コドベースで最も有用な作家であり、私自身も彼のコードをそのまま使っているので、他の人に批評してもらいましょう。 批判ではなく、何ができるかを考えているのですが......。しかし、インタビューにあるように、そして@fxsaber 自身も認めているように、頭痛以外の何物でもありません。 SZZ:小型モンスターの 初期型がより鮮明に見えた可能性が高いですね ;) fxsaber 2021.02.01 16:43 #104 Igor Makanu:ZS:オリジナル版のリトルモンスターは、もっとわかりやすく見える可能性が高いです ;) ZIPから持って きた(一番最初のリリースが含まれている)。 static bool VirtualOrderSelect( const TICKET_TYPE Index, const int Select, const int Pool = MODE_TRADES ) { return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.OrderSelect(Index, Select, Pool) : #ifdef __MQL5__ #ifdef __MT4ORDERS__ ::OrderSelect(Index, Select, Pool) #else // __MT4ORDERS__ false #endif // __MT4ORDERS__ #else // __MQL5__ ::OrderSelect(Index, Select, Pool) #endif // __MQL5__ ); } しかし、その後もどんどん機能が必要になってきて、徐々にコードが肉付けされていきました。Filling機能では違いました。そこで肉付けされたものはなく、一気に書き上げた。 Renat Fatkhullin 2021.02.01 18:23 #105 Vasiliy Sokolov:正確に何をするかは、コンパイラーだけが知っている。最近のコンパイラは驚異的なユーティリティを備えている。一般的なコーダーに適応し、その人が何を必要としているのか、すでによく分かっているのです。コンパイラができることは、短い関数で シンプルでわかりやすいコードを書くことです。コンパイラは、多数の関数ノードからなるソースコードグラフを解析して、結果のプログラムを構築する方が簡単で効率的である。必要な機能が適切な場所に固定されるため、生産性にプラスの効果しかありません。 まったくその通りです。 MQL5の話をするならば、10~20~30年前の「最適化」手法は忘れてもいいのです。最も読みやすいコードを書く必要があります。それであって、ハッカーものでもなく、純粋なスマートさでもない。 なぜ? コンパイラは5〜10サイクルのコード並べ替えを行うため、何十もの最適化パターンを使うまでもなく、驚くほど明快で簡潔なものとなっているのです。 MQL5コンパイラは、+2%の速度を出そうとする人間の試みを面白がっています。 興味のある方は、数学の計算は 分岐なしで進み、1つのコマンド(128ビットのデータ)で2つの根を一度に計算 このコードは次のアセンブラSSEコードに変わる: D1=sqrt((X1-X)*(X1-X)+(Y1-Y)*(Y1-Y)); D2=sqrt((X2-X)*(X2-X)+(Y2-Y)*(Y2-Y)); D3=sqrt((X3-X)*(X3-X)+(Y3-Y)*(Y3-Y)); D4=sqrt((X4-X)*(X4-X)+(Y4-Y)*(Y4-Y)); D5=sqrt((X5-X)*(X5-X)+(Y5-Y)*(Y5-Y)); D6=sqrt((X6-X)*(X6-X)+(Y6-Y)*(Y6-Y)); D7=sqrt((X7-X)*(X7-X)+(Y7-Y)*(Y7-Y)); D8=sqrt((X8-X)*(X8-X)+(Y8-Y)*(Y8-Y)); ... sqrtsd xmm1, xmm1 unpcklpd xmm4, xmm4 movapd xmm3, xmmword ptr [rsp + 432] unpcklpd xmm3, xmmword ptr [rsp + 384] subpd xmm3, xmm4 mulpd xmm3, xmm3 unpcklpd xmm0, xmm0 movapd xmm5, xmmword ptr [rsp + 416] unpcklpd xmm5, xmmword ptr [rsp + 400] subpd xmm5, xmm0 mulpd xmm5, xmm5 addpd xmm5, xmm3 sqrtpd xmm8, xmm5 movapd xmm5, xmmword ptr [rsp + 464] subpd xmm5, xmm4 mulpd xmm5, xmm5 movapd xmm7, xmm9 subpd xmm7, xmm0 mulpd xmm7, xmm7 addpd xmm7, xmm5 movapd xmm6, xmm10 unpcklpd xmm6, xmm11 subpd xmm6, xmm4 movapd xmm3, xmmword ptr [rsp + 368] unpcklpd xmm3, xmmword ptr [rsp + 352] subpd xmm3, xmm0 movapd xmm4, xmm8 shufpd xmm4, xmm4, 1 sqrtpd xmm5, xmm7 mulpd xmm6, xmm6 mulpd xmm3, xmm3 addpd xmm3, xmm6 sqrtpd xmm15, xmm3 movapd xmm0, xmm14 unpcklpd xmm0, xmmword ptr [rsp + 336] subpd xmm0, xmm2 mulpd xmm0, xmm0 movapd xmm2, xmm0 shufpd xmm2, xmm2, 1 addsd xmm2, xmm0 movapd xmm0, xmm15 shufpd xmm0, xmm0, 1 sqrtsd xmm12, xmm2 これは、実は芸術作品なんです。アセンブラコマンドの4回の呼び出しで8個の根が計算された。1回の呼び出しで2つのダブルナンバーが計算される。 配列を処理する場合、チェック、分岐、ダブルから整数へのインデックス変換での損失など、すべて通常通りです。 この例で配列を扱う場合、FPUとALUが常に混在することになり、パフォーマンス上非常に不利です 動的配列アクセスの最適化は、賞賛に値する素晴らしいものです。しかし、FPU/ALU演算+ダブル→整数+分岐の混在は時間を浪費する 一般的な結論は、完璧な最適化により、MQL5では数学が勝利した、というものです。ここで負けるのはアレイではなく、数学の勝利です。 Aleksey Mavrin 2021.02.01 18:29 #106 Georgiy Merts:それはなぜでしょうか?それどころか、「or」演算子よりも「if」2つの方がずっと簡単です。複雑な条件の結果を論理的な "or"("and "と混同しやすい)で把握し、両方の戻り方を追跡するよりも、まず1つの条件を追跡し、それが真なら関数を離れ、次に他の条件をチェックし、それが真なら離れる方が明らかに簡単です。このようなコードの正当性はデバッグにある」と書いてあるのは、かなり面白いです。なぜなら、このようなコードはずっと理解しやすいということだからです(さもなければ、なぜデバッグにあるのでしょうか ?)「神格化」については、fxsaber氏の表現がありますが、彼自身は「このコードは繰り返しテストされており、動作する」と述べるだけで、その仕組みについては言及しませんでした。それは、あってはならないことだと私は思います。このコードは、otfFilingType命令が実行 可能かどうかをチェックし、strSymbolで実行可能であればそれを返し、そうでなければ正解とするものです。 仕組みがまったくわからない。そして、fxsaberの権限にのみ依存する。どなたか解説していただけませんか? 一度座って一歩一歩分解したことがあるのですが、ペンと紙が必要だったようです) なぜこの解析が有用だったかというと、enumの値の整数の関係(enumerationの考え方自体でカプセル化されているはず)を使用しているため、enum構造を変更した場合、すべてが壊れてしまうことが理解できたからです。)私自身は、せいぜいモアレくらいで、これを回避するようにしています。WinAPIを扱っている方にとっては、おなじみでしょう。 Georgiy Merts 2021.02.02 05:03 #107 Andrey Khatimlianskii:理解するには、その扱いにくいリトルーンの表現を分解すればよいのです。 そう、それを試してみたのです。でも、分解するほどのモチベーションはなく...。 Georgiy Merts 2021.02.02 05:14 #108 Renat Fatkhullin:全くその通りです。MQL5の話であれば、10~20~30年前の「最適化」手法は忘れてもいいのです。最も読みやすいコードを書く必要があります。それであって、ハッカーものでもなく、純粋なスマートさでもない。 その通りです。この結論に達したのは、ずいぶん前のことです。でも、コンパイラでよくなると思っているからではありません。しかし、コードの問題の主な原因は人間自身であるため、できるだけシンプルで透明性のあるコードを書くべきだということです。 透明化」できない場合は、なぜこうで、ああでないのか、詳細なコメントを書く必要があります。 そして、コンパイラは...。十分に効率的にできないとしても、プログラムのある側面を考慮していないことによるバグの可能性よりは問題ないでしょう。 Vasiliy Sokolov 2021.02.02 11:06 #109 fxsaber:コードは非常にシンプルで短いものです(説明)。FPに書けば、比較できて面白いかもしれませんね。 お願いします。C#をFPスタイルで。 using System; using System.Linq; using System.Collections.Generic; using static FeesCalculator.FeesCalcs; using System.Text; using static System.Math; namespace FeesCalculator { public static class EnumerableExt { /// <summary> /// Call of function 'action' for each element if sequence (mapping). /// </summary> /// <typeparam name="T"></typeparam> /// <param name="seq">Enumerable sequence</param> /// <param name="action">Need action</param> public static void Map<T>(this IEnumerable<T> seq, Action<T> action) { foreach (var item in seq) action(item); } } /// <summary> /// Инвестиционный результат /// </summary> public record AccountRecord { public double Investor { get; init; } public double Manager { get; init; } public double Summary { get; init; } public static AccountRecord operator *(AccountRecord r, double v) { return new AccountRecord { Investor = r.Investor * v, Manager = r.Manager * v, Summary = r.Summary * v }; } public override string ToString() { StringBuilder sb = new StringBuilder(); sb.Append(nameof(Investor)).Append(" = ").Append(Investor.ToString("F4")).Append(' '); sb.Append(nameof(Manager)).Append(" = ").Append(Manager.ToString("F4")).Append(' '); sb.Append(nameof(Summary)).Append(" = ").Append(Summary.ToString("F4")); return sb.ToString(); } } /// <summary> /// Параметры оферты /// </summary> public record PammSet { /// <summary> /// Доходность за расчетный период /// </summary> public double Perfomance { get; init; } /// <summary> /// Вознаграждение управляющего /// </summary> public double Gift { get; init; } /// <summary> /// Количество расчетных периодов /// </summary> public int N { get; init; } /// <inheritdoc/> public override string ToString() { StringBuilder str = new StringBuilder(); str.Append("Доходность за расчетный период: ").Append((Perfomance * 100.0).ToString("F1")).Append("%\t\n"); str.Append("Вознаграждение управляющего: ").Append((Gift * 100.0).ToString("F1")).Append("%\t\n"); str.Append("Количество расчетных периодов: ").Append(N); return str.ToString(); } } /// <summary> /// Формулы расчета /// </summary> public class FeesCalcs { /// <summary> /// Если управляющий снимает деньги в конце каждого расчетного периода /// </summary> /// <param name="Performance"></param> /// <param name="Gift"></param> /// <param name="N"></param> /// <returns></returns> public static AccountRecord Set1(PammSet set) { Func<double> investor = () => Pow(1 + (set.Perfomance) * (1 - set.Gift), set.N); Func<double> manager = () => (investor() - 1) * set.Gift / (1 - set.Gift); AccountRecord ac = new AccountRecord { Investor = investor(), Manager = manager(), Summary = investor() + manager() }; return ac; } /// <summary> /// Если ничего не делалось в расчетные периоды /// </summary> /// <param name="Performance"></param> /// <param name="Gift"></param> /// <param name="N"></param> /// <returns></returns> public static AccountRecord Set2(PammSet set) { Func<double> summary = () => Pow(set.Perfomance + 1, set.N); Func<double> manager = () => (summary() - 1) * set.Gift; double s = summary(); double d = manager(); AccountRecord ac = new AccountRecord { Summary = summary(), Manager = manager(), Investor = summary() - manager() }; return ac; } /// <summary> /// Если управляющий снимает деньги в конце каждого расчетного периода и реинвестирует их /// </summary> /// <param name="Performance"></param> /// <param name="Gift"></param> /// <param name="N"></param> /// <returns></returns> public static AccountRecord Set3(PammSet set) { Func<double> summary = () => Pow(set.Perfomance + 1, set.N); Func<double> investor = () => Pow(1 + (set.Perfomance) * (1 - set.Gift), set.N); return new AccountRecord { Summary = summary(), Investor = investor(), Manager = summary() - investor() }; } /// <summary> /// Сопостовление: описание - функция расчета /// </summary> public static readonly Dictionary<string, Func<PammSet, AccountRecord>> DescrToAccountRecord = new Dictionary<string, Func<PammSet, AccountRecord>> { {"Если управляющий снимает деньги в конце каждого расчетного периода (1)", Set1 }, {"Если ничего не делалось в расчетные периоды (2)", Set2 }, {"Если управляющий снимает деньги в конце каждого расчетного периода и реинвестирует их (3)", Set3 }, }; } class Program { static void Main(string[] args) { var _ = args.Select((a) => double.Parse(a)).Take(3).ToList(); PammSet pamm = new PammSet { Perfomance = _[0]/100.0, Gift = _[1]/100.0, N = (int)_[2] }; Console.WriteLine($"Данные для инвестиционного счета со следующими характеристиками:\n\n{pamm}\n"); Console.WriteLine("Конечный результат для Инвестора, Управляющего и Суммарно:\n"); Func<KeyValuePair<string, Func<PammSet, AccountRecord>>, string> f = (kvp) => kvp.Key + ".\n" + kvp.Value(pamm).ToString() + "\n"; Enumerable.Select(DescrToAccountRecord, f).Map((s) => Console.WriteLine(s)); Console.WriteLine(pamm); Func<int, PammSet> toPamm = (n) => new PammSet { Perfomance = pamm.Perfomance, Gift = pamm.Gift, N = n }; Func<PammSet, IEnumerable<AccountRecord>> toAccs = (n) => DescrToAccountRecord.Select((s) => s.Value(n)); var accounts = Enumerable.Repeat(1, pamm.N).Select((a, b) => a + b).Select(toPamm).Select(toAccs); Func<AccountRecord, string> toString = (ar) => ar.Investor.ToString("F2") + "\t" + ar.Manager.ToString("F2") + "\t" + ar.Summary.ToString("F2") + "\t"; int period = default; accounts.Map ( (en) => { Console.Write($"{++period}:\t"); en.Map((ar) => Console.Write(toString(ar))); Console.WriteLine(); } ); } } } もちろん、FPはかなり曲がっています(曲がったFPコーダーによって、不完全なFP言語C#で書かれたため)。しかし、目標は、現代のOOPジャーゴンで、FPでもそれができることを示すことなのです。もちろん、F#やHaskellのような限定的なものではありませんが、FPスタイルで書くことは誰も禁じていません。不変性、高階関数、クロージャ、マッピングなどを利用する。- 全部やってもいいんですよ。しかし、これではなぜかコードが完璧にならない。 s.w.全体のコード構成は意図的にオリジナルを模倣しています。いい意味でFPとは全く違うはずなのに、複雑なオブジェクトやMapを模したフォアグラウンドがなく、作者は自分のできる範囲で絵を描いている。 fxsaber 2021.02.02 13:01 #110 Vasiliy Sokolov:お願いします。C#をFPスタイルで。 習慣や構文の知識の問題であることは理解していますが、原作者であるにもかかわらず、コードに入り込むのに非常に苦労しています。 トレーディング、自動売買システム、ストラテジーテストに関するフォーラム OOPに関する興味深い意見 fxsaber, 2021.01.29 13:39 些細なことです。 #property strict #property script_show_inputs input double inPerformance = 100; // Сколько процентов дает система за период input double inGift = 50; // Награда управляющего в процентах (< 100) input int inN = 12; // Сколько расчетных периодов struct BASE { double Investor; double Manager; double Summary; // Если управляющий снимает деньги в конце каждого расчетного периода. void Set1( const double Performance, const double Gift, const int N ) { this.Investor = ::MathPow(1 + (Performance - 1)* (1 - Gift), N); this.Manager = (this.Investor - 1) * Gift / (1 - Gift); this.Summary = this.Investor + this.Manager; return; } // Если ничего не делалось в расчетные периоды. void Set2( const double Performance, const double Gift, const int N ) { this.Summary = ::MathPow(Performance, N); this.Manager = (this.Summary - 1) * Gift; this.Investor = this.Summary - this.Manager; return; } // Если управляющий снимает деньги в конце каждого расчетного периода и реинвестирует их. void Set3( const double Performance, const double Gift, const int N ) { this.Summary = ::MathPow(Performance, N); this.Investor = ::MathPow(1 + (Performance - 1)* (1 - Gift), N); this.Manager = this.Summary - this.Investor; return; } void operator *=( const double Deposit = 1 ) { this.Investor *= Deposit; this.Manager *= Deposit; this.Summary *= Deposit; return; } #define TOSTRING(A) #A + " = " + ::DoubleToString(A, 4) + " " string ToString( const bool FlagName = true ) const { return(FlagName ? TOSTRING(Investor) + TOSTRING(Manager) + TOSTRING(Summary) : ::StringFormat("||%-12.4f||%-12.4f||%-12.4f||", this.Investor, this.Manager, this.Summary)); } #undef TOSTRING }; struct PAMM { double Performance; // Доходность за расчетный период double Gift; // Вознагражение управляющего. int N; // Сколько расчетных периодов. BASE Base1; // Если управляющий снимает деньги в конце каждого расчетного периода. BASE Base2; // Если ничего не делалось в расчетные периоды. BASE Base3; // Если управляющий снимает деньги в конце каждого расчетного периода и реинвестирует их. void Set( const double dPerformance, const double dGift, const int iN ) { this.Performance = dPerformance; this.Gift = dGift; this.N = iN; this.Base1.Set1(1 + this.Performance / 100, this.Gift / 100, this.N); this.Base2.Set2(1 + this.Performance / 100, this.Gift / 100, this.N); this.Base3.Set3(1 + this.Performance / 100, this.Gift / 100, this.N); } void operator *=( const double Deposit = 1 ) { this.Base1 *= Deposit; this.Base2 *= Deposit; this.Base3 *= Deposit; return; } string GetDescription( void ) const { return("Доходность за расчетный период " + ::DoubleToString(this.Performance, 1) + "%\n" + "Вознагражение управляющего " + ::DoubleToString(this.Gift, 1) + "%\n" + "Количество расчетных периодов. " + (string)this.N); } string ToString( const bool FlagName = true, const bool FlagDescription = true ) const { return(FlagDescription ? "Данные для инвестиционного счета со следующими характеристиками:\n\n" + this.GetDescription() + "\n\nКонечный результат для Инвестора, Управляющего и Суммарно:" "\n\nЕсли управляющий снимает деньги в конце каждого расчетного периода (1).\n" + this.Base1.ToString(FlagName) + "\n\nЕсли ничего не делалось в расчетные периоды (2).\n" + this.Base2.ToString(FlagName) + "\n\nЕсли управляющий снимает деньги в конце каждого расчетного периода и реинвестирует их (3).\n" + this.Base3.ToString(FlagName) : this.Base1.ToString(FlagName) + this.Base2.ToString(FlagName) + this.Base3.ToString(FlagName)); } }; void OnStart() { PAMM Pamm; Pamm.Set(inPerformance, inGift, inN); Print(Pamm.ToString()); string Str = Pamm.GetDescription() + "\n "; for (int i = 1; i <= 3; i++ ) Str += ::StringFormat("||%-12s||%-12s||%-12s||", "Investor" + (string)i, "Manager" + (string)i, "Summary" + (string)i); for (int i = 1; i <= inN; i++ ) { Pamm.Set(inPerformance, inGift, i); Str += StringFormat("\n%-2d:", i) + Pamm.ToString(false, false); } Print(Str); } 技術的にはOOPなんでしょうけど。でも、一番原始的なところ。それがないとできないんですけどね。可能性、間抜けな脳内リア充とリベンジこれ。 1...45678910111213 新しいコメント 取引の機会を逃しています。 無料取引アプリ 8千を超えるシグナルをコピー 金融ニュースで金融マーケットを探索 新規登録 ログイン スペースを含まないラテン文字 このメールにパスワードが送信されます エラーが発生しました Googleでログイン WebサイトポリシーおよびMQL5.COM利用規約に同意します。 新規登録 MQL5.com WebサイトへのログインにCookieの使用を許可します。 ログインするには、ブラウザで必要な設定を有効にしてください。 ログイン/パスワードをお忘れですか? Googleでログイン
「神格化」については、fxsaber氏の表現がありますが、彼自身は「このコードは繰り返しテストされており、動作する」と述べるだけで、その仕組みについては言及しませんでした。それは、あってはならないことだと私は思います。
このコードは、otfFilingType命令が実行 可能かどうかをチェックし、strSymbolで実行可能であればそれを返し、そうでなければ正解とするものです。
仕組みがまったくわからない。そして、fxsaberの権限にのみ依存すること。
どなたか解説していただけませんか?
それを理解するためには、この面倒な返り値を構成要素に分解すればよい。
"目的は手段を正当化する "の例ですね。
このコードはスパゲティみたいなものですが、おそらく今コドベースで最も有用な作家であり、私自身彼のコードをそのまま使っていることを考えると、他の人に批評してもらいましょう。
ちなみにこのコードはスパゲッティみたいなものですが、おそらく今コドベースで最も有用な作家であり、私自身も彼のコードをそのまま使っているので、他の人に批評してもらいましょう。
批判ではなく、何ができるかを考えているのですが......。しかし、インタビューにあるように、そして@fxsaber 自身も認めているように、頭痛以外の何物でもありません。
SZZ:小型モンスターの 初期型がより鮮明に見えた可能性が高いですね ;)
ZS:オリジナル版のリトルモンスターは、もっとわかりやすく見える可能性が高いです ;)
ZIPから持って きた(一番最初のリリースが含まれている)。
しかし、その後もどんどん機能が必要になってきて、徐々にコードが肉付けされていきました。Filling機能では違いました。そこで肉付けされたものはなく、一気に書き上げた。
正確に何をするかは、コンパイラーだけが知っている。最近のコンパイラは驚異的なユーティリティを備えている。一般的なコーダーに適応し、その人が何を必要としているのか、すでによく分かっているのです。コンパイラができることは、短い関数で シンプルでわかりやすいコードを書くことです。コンパイラは、多数の関数ノードからなるソースコードグラフを解析して、結果のプログラムを構築する方が簡単で効率的である。必要な機能が適切な場所に固定されるため、生産性にプラスの効果しかありません。
まったくその通りです。
MQL5の話をするならば、10~20~30年前の「最適化」手法は忘れてもいいのです。最も読みやすいコードを書く必要があります。それであって、ハッカーものでもなく、純粋なスマートさでもない。
なぜ?
コンパイラは5〜10サイクルのコード並べ替えを行うため、何十もの最適化パターンを使うまでもなく、驚くほど明快で簡潔なものとなっているのです。
MQL5コンパイラは、+2%の速度を出そうとする人間の試みを面白がっています。
これは、実は芸術作品なんです。アセンブラコマンドの4回の呼び出しで8個の根が計算された。1回の呼び出しで2つのダブルナンバーが計算される。興味のある方は、数学の計算は 分岐なしで進み、1つのコマンド(128ビットのデータ)で2つの根を一度に計算
このコードは次のアセンブラSSEコードに変わる:
一般的な結論は、完璧な最適化により、MQL5では数学が勝利した、というものです。ここで負けるのはアレイではなく、数学の勝利です。
それはなぜでしょうか?
それどころか、「or」演算子よりも「if」2つの方がずっと簡単です。
複雑な条件の結果を論理的な "or"("and "と混同しやすい)で把握し、両方の戻り方を追跡するよりも、まず1つの条件を追跡し、それが真なら関数を離れ、次に他の条件をチェックし、それが真なら離れる方が明らかに簡単です。
このようなコードの正当性はデバッグにある」と書いてあるのは、かなり面白いです。なぜなら、このようなコードはずっと理解しやすいということだからです(さもなければ、なぜデバッグにあるのでしょうか ?)
「神格化」については、fxsaber氏の表現がありますが、彼自身は「このコードは繰り返しテストされており、動作する」と述べるだけで、その仕組みについては言及しませんでした。それは、あってはならないことだと私は思います。
このコードは、otfFilingType命令が実行 可能かどうかをチェックし、strSymbolで実行可能であればそれを返し、そうでなければ正解とするものです。
仕組みがまったくわからない。そして、fxsaberの権限にのみ依存する。
どなたか解説していただけませんか?
一度座って一歩一歩分解したことがあるのですが、ペンと紙が必要だったようです)
なぜこの解析が有用だったかというと、enumの値の整数の関係(enumerationの考え方自体でカプセル化されているはず)を使用しているため、enum構造を変更した場合、すべてが壊れてしまうことが理解できたからです。)私自身は、せいぜいモアレくらいで、これを回避するようにしています。WinAPIを扱っている方にとっては、おなじみでしょう。
理解するには、その扱いにくいリトルーンの表現を分解すればよいのです。
そう、それを試してみたのです。でも、分解するほどのモチベーションはなく...。
全くその通りです。
MQL5の話であれば、10~20~30年前の「最適化」手法は忘れてもいいのです。最も読みやすいコードを書く必要があります。それであって、ハッカーものでもなく、純粋なスマートさでもない。
その通りです。この結論に達したのは、ずいぶん前のことです。でも、コンパイラでよくなると思っているからではありません。しかし、コードの問題の主な原因は人間自身であるため、できるだけシンプルで透明性のあるコードを書くべきだということです。
透明化」できない場合は、なぜこうで、ああでないのか、詳細なコメントを書く必要があります。
そして、コンパイラは...。十分に効率的にできないとしても、プログラムのある側面を考慮していないことによるバグの可能性よりは問題ないでしょう。
コードは非常にシンプルで短いものです(説明)。FPに書けば、比較できて面白いかもしれませんね。
お願いします。C#をFPスタイルで。
もちろん、FPはかなり曲がっています(曲がったFPコーダーによって、不完全なFP言語C#で書かれたため)。しかし、目標は、現代のOOPジャーゴンで、FPでもそれができることを示すことなのです。もちろん、F#やHaskellのような限定的なものではありませんが、FPスタイルで書くことは誰も禁じていません。不変性、高階関数、クロージャ、マッピングなどを利用する。- 全部やってもいいんですよ。しかし、これではなぜかコードが完璧にならない。
s.w.全体のコード構成は意図的にオリジナルを模倣しています。いい意味でFPとは全く違うはずなのに、複雑なオブジェクトやMapを模したフォアグラウンドがなく、作者は自分のできる範囲で絵を描いている。
お願いします。C#をFPスタイルで。
習慣や構文の知識の問題であることは理解していますが、原作者であるにもかかわらず、コードに入り込むのに非常に苦労しています。
トレーディング、自動売買システム、ストラテジーテストに関するフォーラム
OOPに関する興味深い意見
fxsaber, 2021.01.29 13:39
些細なことです。
技術的にはOOPなんでしょうけど。でも、一番原始的なところ。それがないとできないんですけどね。可能性、間抜けな脳内リア充とリベンジこれ。