"Апофеозом" считаю одно выражение fxsaber'a, про которое он сам не смог сказать, как оно работает, заявив просто, что "код многократно оттестирован, и работает". Такого, на мой взгляд, быть не должно:
Этот код проверяет возможность исполнения ордера otfFilingType, и возвращает его, если он доступен на символе strSymbol, иначе - корректный вариант.
Я совершенно не могу понять, как он работает. И только полагаюсь на авторитет fxsaber'a.
Может быть, кто-нибудь объяснит ?
Чтобы понять, достаточно разобрать это громоздкое выражение из ретурна на составляющие.
кстати этот код как раз похож на спагетти, но с учетом того что это наверное самый полезный автор в кодобазе сейчас и я сам пользую его коды as is, пусть кто-нибудь другой критикует
кстати этот код как раз похож на спагетти, но с учетом того что это наверное самый полезный автор в кодобазе сейчас и я сам пользую его коды as is, пусть кто-нибудь другой критикует
речь не идет о критике, я пытаюсь разобраться, что это может дать.... но как показала беседа, да и сам @fxsaber коственно признался - ничего кроме головной боли
ЗЫ: высока вероятность, что первоначальный вариант маленького монстра выглядел более наглядно ;)
Но после этого требовалось все больше функционала, и код медленно обрастал мясом. С Filling-функцией было иначе. Там ничего не обрастало, сразу писалось.
Как точно сделает компилятор знает только он сам. В современные компиляторы заложены ошеломляющие евристики. Они подстраиваются под среднего кодера, и уже лучше знают что ему нужно. Лучшее, что можно сделать для компилятора, - это писать простой, понятный код с короткими функциями. Компилятору гораздо проще и эффективней анализировать граф исходного кода, состоящий из множества функций-узлов, для построения итоговой программы. На производительности это скажется только положительно, так как нужные функции заинлайнятся в нужные места.
Абсолютно верно.
Если говорить про MQL5, то можно забыть про методы "оптимизаций" 10-20-30 летней давности. Писать надо максимально читабельный код. Именно он является мерилом качества, а не хакерские навороты и чистые понты.
Почему?
Да потому, что компилятор пройдет 5-10 циклов переупорядочивания кода, изумительно четко и коротко выведет концы графов, не говоря уже о применении десятков паттернов оптимизации.
MQL5 компилятору смешно от человеческих попыток наворотами сделать +2% скорости.
Как раз наоборот, с двумя "ифами" - куда проще, чем с оператором "или".
Явно проще проследить сперва одно условие, и уйти из функции, в случае выполнения, а потом проверить другое условие, и тоже уйти, в случае выполнения. Чем прикидывать, что получается в результате сложного условия через логическое "или" (которое запросто можно спутать и "и"), и следить за обоими вариантами возврата.
Довольно смешно читать ниже, что "оправдание такому - отладка", ведь это и значит, что такой код куда более понятен (иначе зачем он в отладке ?).
"Апофеозом" считаю одно выражение fxsaber'a, про которое он сам не смог сказать, как оно работает, заявив просто, что "код многократно оттестирован, и работает". Такого, на мой взгляд, быть не должно:
Этот код проверяет возможность исполнения ордера otfFilingType, и возвращает его, если он доступен на символе strSymbol, иначе - корректный вариант.
Я совершенно не могу понять, как он работает. И только полагаюсь на авторитет fxsaber'a.
Может быть, кто-нибудь объяснит ?
Я когда-то сел и разобрал поэтапно, кажется понадобилась ручка с бумажкой)
Для чего этот разбор пригодился - я понял что в случае смены структуры перечислений всё сломается) т.к. используются целочисленные отношения значений перечислений (которые по самой идее перечислений как раз должны быть инкапсулированы). Стараюсь сам такого избегать, максимум отношения больше-меньше. Для имеющих дело с WinAPI наверное привычно.
Если говорить про MQL5, то можно забыть про методы "оптимизаций" 10-20-30 летней давности. Писать надо максимально читабельный код. Именно он является мерилом качества, а не хакерские навороты и чистые понты.
Вот-вот. Я уже давно к этому выводу пришел. Но не потому, что думаю, что компилятор сделает лучше. А потому, что главный источник проблем в коде - это сам человек, а значит, надо писать код по возможности так, чтобы код был максимально прост и прозрачен.
Там, где "прозрачно" сделать не получается - обязательны подробные комментарии, почему именно так, а не иначе.
Ну а компилятор... даже если он сделает недостаточно эффективно - это меньшая проблема, чем потенциальный баг из-за того, что ты не учтешь какие-то моменты работы программы.
Код очень простой и короткий (описание). Если его напишите на ФП, будет интересно сравнить.
Пожалуйста. C# в ФП стиле:
using System;
using System.Linq;
using System.Collections.Generic;
using static FeesCalculator.FeesCalcs;
using System.Text;
using static System.Math;
namespace FeesCalculator
{
publicstaticclass 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>publicstaticvoid Map<T>(this IEnumerable<T> seq, Action<T> action)
{
foreach (var item in seq)
action(item);
}
}
/// <summary>/// Инвестиционный результат/// </summary>public record AccountRecord
{
publicdouble Investor { get; init; }
publicdouble Manager { get; init; }
publicdouble Summary { get; init; }
publicstatic AccountRecord operator *(AccountRecord r, double v)
{
returnnew AccountRecord
{
Investor = r.Investor * v,
Manager = r.Manager * v,
Summary = r.Summary * v
};
}
publicoverridestring 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>publicdouble Perfomance { get; init; }
/// <summary>/// Вознаграждение управляющего/// </summary>publicdouble Gift { get; init; }
/// <summary>/// Количество расчетных периодов/// </summary>publicint N { get; init; }
/// <inheritdoc/>publicoverridestring 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>publicclass FeesCalcs
{
/// <summary>/// Если управляющий снимает деньги в конце каждого расчетного периода/// </summary>/// <param name="Performance"></param>/// <param name="Gift"></param>/// <param name="N"></param>/// <returns></returns>publicstatic 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>publicstatic 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>publicstatic 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);
returnnew AccountRecord
{
Summary = summary(),
Investor = investor(),
Manager = summary() - investor()
};
}
/// <summary>/// Сопостовление: описание - функция расчета/// </summary>publicstatic readonly Dictionary<string, Func<PammSet, AccountRecord>> DescrToAccountRecord = new Dictionary<string, Func<PammSet, AccountRecord>>
{
{"Если управляющий снимает деньги в конце каждого расчетного периода (1)", Set1 },
{"Если ничего не делалось в расчетные периоды (2)", Set2 },
{"Если управляющий снимает деньги в конце каждого расчетного периода и реинвестирует их (3)", Set3 },
};
}
class Program
{
staticvoid 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();
}
);
}
}
}
ФП весьма кривоват конечно (так как писал кривой кодер ФПешник, на неполноценном ФП языке C#).Но цель показать что на современных ООП ЯПах можно и в ФП. Ограничено конечно, это не F# или Haskell, но писать в ФП стиле никто не запрещает. Использовать иммутабельность, функции высшего порядка, замыкания, сопоставления и т.д. - все можно, пожалуйста. Только код от этого не становится идеальным почему-то.
з.ы. Общая структура кода намерено мимикрирует под оригинал. Хотя по-хорошему в ФП нужно совсем уж по-другому, без сложных объектов и foreach мимикрирующего под Map, но художник рисовал как мог.
"Апофеозом" считаю одно выражение fxsaber'a, про которое он сам не смог сказать, как оно работает, заявив просто, что "код многократно оттестирован, и работает". Такого, на мой взгляд, быть не должно:
Этот код проверяет возможность исполнения ордера otfFilingType, и возвращает его, если он доступен на символе strSymbol, иначе - корректный вариант.
Я совершенно не могу понять, как он работает. И только полагаюсь на авторитет fxsaber'a.
Может быть, кто-нибудь объяснит ?
Чтобы понять, достаточно разобрать это громоздкое выражение из ретурна на составляющие.
Ваш пример из "цель оправдывает средства"
кстати этот код как раз похож на спагетти, но с учетом того что это наверное самый полезный автор в кодобазе сейчас и я сам пользую его коды as is, пусть кто-нибудь другой критикует
кстати этот код как раз похож на спагетти, но с учетом того что это наверное самый полезный автор в кодобазе сейчас и я сам пользую его коды as is, пусть кто-нибудь другой критикует
речь не идет о критике, я пытаюсь разобраться, что это может дать.... но как показала беседа, да и сам @fxsaber коственно признался - ничего кроме головной боли
ЗЫ: высока вероятность, что первоначальный вариант маленького монстра выглядел более наглядно ;)
ЗЫ: высока вероятность, что первоначальный вариант маленького монстра выглядел более наглядно ;)
Взял из ZIP (содержит самый первый релиз).
Но после этого требовалось все больше функционала, и код медленно обрастал мясом. С Filling-функцией было иначе. Там ничего не обрастало, сразу писалось.
Как точно сделает компилятор знает только он сам. В современные компиляторы заложены ошеломляющие евристики. Они подстраиваются под среднего кодера, и уже лучше знают что ему нужно. Лучшее, что можно сделать для компилятора, - это писать простой, понятный код с короткими функциями. Компилятору гораздо проще и эффективней анализировать граф исходного кода, состоящий из множества функций-узлов, для построения итоговой программы. На производительности это скажется только положительно, так как нужные функции заинлайнятся в нужные места.
Абсолютно верно.
Если говорить про MQL5, то можно забыть про методы "оптимизаций" 10-20-30 летней давности. Писать надо максимально читабельный код. Именно он является мерилом качества, а не хакерские навороты и чистые понты.
Почему?
Да потому, что компилятор пройдет 5-10 циклов переупорядочивания кода, изумительно четко и коротко выведет концы графов, не говоря уже о применении десятков паттернов оптимизации.
MQL5 компилятору смешно от человеческих попыток наворотами сделать +2% скорости.
Кому интересно, зацените как 8 квадратных корней в разных выражениях были переупорядочены и вычислены за 4 ассемблерные команды.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Ошибки, баги, вопросы
Renat Fatkhullin, 2018.03.13 22:59
Проверка показала, что:
Вот этот код превращается в следующий ассемблерный SSE код:
Это произведение исскуства вообще-то. 8 корней вычислено за 4 вызова ассемблерной команды. Два double числа вычислялись за один вызов.
Общий вывод: математика в MQL5 побеждает за счет идеальной оптимизации. Тут не массивы проигрывают, а математика выигрывает.
С чего это ?
Как раз наоборот, с двумя "ифами" - куда проще, чем с оператором "или".
Явно проще проследить сперва одно условие, и уйти из функции, в случае выполнения, а потом проверить другое условие, и тоже уйти, в случае выполнения. Чем прикидывать, что получается в результате сложного условия через логическое "или" (которое запросто можно спутать и "и"), и следить за обоими вариантами возврата.
Довольно смешно читать ниже, что "оправдание такому - отладка", ведь это и значит, что такой код куда более понятен (иначе зачем он в отладке ?).
"Апофеозом" считаю одно выражение fxsaber'a, про которое он сам не смог сказать, как оно работает, заявив просто, что "код многократно оттестирован, и работает". Такого, на мой взгляд, быть не должно:
Этот код проверяет возможность исполнения ордера otfFilingType, и возвращает его, если он доступен на символе strSymbol, иначе - корректный вариант.
Я совершенно не могу понять, как он работает. И только полагаюсь на авторитет fxsaber'a.
Может быть, кто-нибудь объяснит ?
Я когда-то сел и разобрал поэтапно, кажется понадобилась ручка с бумажкой)
Для чего этот разбор пригодился - я понял что в случае смены структуры перечислений всё сломается) т.к. используются целочисленные отношения значений перечислений (которые по самой идее перечислений как раз должны быть инкапсулированы). Стараюсь сам такого избегать, максимум отношения больше-меньше. Для имеющих дело с WinAPI наверное привычно.
Чтобы понять, достаточно разобрать это громоздкое выражение из ретурна на составляющие.
Да, я так и попытался. Но, не хватило мотивации разбирать...
Абсолютно верно.
Если говорить про MQL5, то можно забыть про методы "оптимизаций" 10-20-30 летней давности. Писать надо максимально читабельный код. Именно он является мерилом качества, а не хакерские навороты и чистые понты.
Вот-вот. Я уже давно к этому выводу пришел. Но не потому, что думаю, что компилятор сделает лучше. А потому, что главный источник проблем в коде - это сам человек, а значит, надо писать код по возможности так, чтобы код был максимально прост и прозрачен.
Там, где "прозрачно" сделать не получается - обязательны подробные комментарии, почему именно так, а не иначе.
Ну а компилятор... даже если он сделает недостаточно эффективно - это меньшая проблема, чем потенциальный баг из-за того, что ты не учтешь какие-то моменты работы программы.
Код очень простой и короткий (описание). Если его напишите на ФП, будет интересно сравнить.
Пожалуйста. C# в ФП стиле:
ФП весьма кривоват конечно (так как писал кривой кодер ФПешник, на неполноценном ФП языке C#).Но цель показать что на современных ООП ЯПах можно и в ФП. Ограничено конечно, это не F# или Haskell, но писать в ФП стиле никто не запрещает. Использовать иммутабельность, функции высшего порядка, замыкания, сопоставления и т.д. - все можно, пожалуйста. Только код от этого не становится идеальным почему-то.
з.ы. Общая структура кода намерено мимикрирует под оригинал. Хотя по-хорошему в ФП нужно совсем уж по-другому, без сложных объектов и foreach мимикрирующего под Map, но художник рисовал как мог.
Пожалуйста. C# в ФП стиле:
Понимаю, что дело в привычке и знании синтаксиса, но мне очень тяжело въехать в код даже при том, что являюсь автором оригинала.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Интересное мнение про ООП
fxsaber, 2021.01.29 13:39
Портянка.
Формально, наверное, это ООП. Но самая его примитивная часть. Однако, без нее не смог. Возможно, тупо мозг перестроился на другое и клепаю такое.