Optimal F Service
- Utilitaires
- Version: 1.0
- Activations: 10
Service Optimal F
- Type d'application : Service
- Fonctions de l'application : Calcul de la fraction optimale et du volume d'opérations pour maximiser la croissance de la courbe de capital, basé sur les résultats des opérations précédentes.
À propos de cette application
La gestion du capital est le composant le plus crucial et souvent sous-estimé de tout système de trading. Une gestion appropriée peut améliorer—et dans certains cas de manière significative—les performances de votre algorithme de trading.
Cette application calcule automatiquement la fraction optimale et le volume d'opérations en utilisant l'algorithme proposé par Ralph Vince dans son livre The Mathematics of Money Management. Cet algorithme vise une croissance géométrique maximale du solde du compte. Ce point est unique pour chaque système de trading et il est essentiel de le connaître. Dans vos systèmes de trading, vous ne devez jamais utiliser une taille d'opération qui dépasse la valeur optimale !
Les algorithmes de gestion du capital ne sont pas conçus pour les systèmes perdants sur le plan mathématique, basés sur des moyennes, des martingales ou des stratégies similaires. Ces systèmes seront filtrés par l'application avant tout calcul, car leur fraction optimale et leur volume d'opérations sont toujours égaux à zéro. Les algorithmes de gestion du capital peuvent uniquement améliorer les résultats pour les systèmes de trading mathématiquement rentables (ceux ayant une espérance mathématique positive). Ce service est donc recommandé uniquement aux professionnels qui comprennent ce qu'ils font.
Par ailleurs, l'algorithme ne prend pas en compte les corrélations (dépendances) entre les systèmes qui fonctionnent simultanément. Pour que l'algorithme fonctionne efficacement, un ensemble bien diversifié de systèmes de trading est nécessaire.
Comment utiliser
Paramètres :
- LOG_LEVEL - Niveau de journalisation pour la section Experts du terminal. DEBUG fournit les informations les plus détaillées, tandis qu'ERROR enregistre le minimum.
- MAGIC_LIST - Liste d'identifiants des systèmes (Magic Numbers) séparés par des virgules, pour lesquels des calculs sont nécessaires.
- TRADE_FILES_PATH - Chemin du répertoire contenant les fichiers avec les résultats des opérations précédentes (relatif au dossier <Données>/MQL5/Files/).
- OUTPUT_FILE_PATH - Chemin du fichier où seront enregistrés les résultats des calculs (relatif au dossier <Données>/MQL5/Files/).
- WORK_PERIOD - Fréquence des recalculs en secondes.
- BALANCE_MATRIX_PERIOD - Période sur laquelle les résultats sont agrégés, avec des calculs basés sur cette période agrégée plutôt que sur chaque opération individuelle.
Avant le premier lancement, chaque système de trading doit être testé dans le simulateur de stratégies jusqu'à la date actuelle. Il est recommandé de sélectionner une période incluant au moins 100 opérations. Utilisez le Test Trade Saver Script et suivez les instructions pour extraire les fichiers de résultats des tests (*.tst) au format requis.
Si le système de trading a déjà été utilisé dans le terminal et que des positions dans l’historique contiennent le MAGIC spécifié, configurez un paramètre CUSTOM_MAGIC_NUMBER différent dans le script !
Ensuite, pour garantir que les fichiers de données soient mis à jour régulièrement, exécutez le Trade Saver Service en suivant les instructions.
Après l’exportation initiale des données depuis les tests avec le Trade Saver Script, le Trade Saver Service mettra à jour continuellement les fichiers avec de nouvelles données à mesure qu'elles seront disponibles, tandis que le Service Optimal F calculera et enregistrera régulièrement de nouvelles valeurs dans le fichier de résultats.
Algorithme :
- Extraire la liste des systèmes nécessitant des calculs à partir du paramètre MAGIC_LIST.
- Utiliser des fichiers texte nommés <MAGIC>.csv au format <MAGIC>,<POSITION_CLOSE_TIME>,<LOTS>,< RESULT_$>, contenant les résultats des opérations précédentes, depuis le répertoire spécifié par TRADE_FILES_PATH. Construire une matrice pour la fonction de courbe de balance, où chaque valeur a[i][j] représente le résultat du système de trading i pour la période j.
- Vérifier chaque système pour au moins une période négative dans ses résultats. Si un système n’a pas de périodes négatives, l’exclure des calculs suivants (ces systèmes doivent être éliminés).
- Évaluer l’espérance mathématique de chaque système. Si un système n’a pas une valeur espérée positive, l’exclure des calculs suivants (ces systèmes doivent être éliminés).
- Déterminer la marge d’erreur nécessaire pour calculer le volume d’opérations avec une précision de 0,01.
- Pour chaque système restant, calculer sa fraction optimale.
- Diviser le solde actuel en parts égales pour les systèmes restants. Pour chaque système et son solde assigné, calculer le volume d’opérations en lots correspondant à la fraction optimale.
- Écrire les résultats dans le fichier texte spécifié par OUTPUT_FILE_PATH, au format <MAGIC>,<BIGGEST_LOSS>,<OPTIMAL_F>,<OPTIMAL_LOTS>.
Liens et références
Ralph Vince - The Mathematics of Money Management: Risk Analysis Techniques for Traders (ISBN-13: 978-0471547389)
Pour les développeurs
Vous pouvez utiliser la classe suivante pour intégrer les résultats dans vos systèmes de trading :
#include "OptimalFResultsLoader.mqh" // create loader COptimalFResultsLoader* optimalFResultsLoader = new COptimalFResultsLoader("/SRProject/results.csv"); // print all fields for magic = '1111' Print(optimalFResultsLoader.getOptimalFFor(1111), " ", optimalFResultsLoader.getBiggestLossFor(1111), " ", optimalFResultsLoader.getOptimalLotsFor(1111)); // delete loader from memory delete(optimalFResultsLoader);
//+------------------------------------------------------------------+ //| OptimalFResultsLoader.mqh | //| Semyon Racheev | //| | //+------------------------------------------------------------------+ #property copyright "Semyon Racheev" #property link "" #property version "1.00" #include <Files\FileTxt.mqh> class COptimalFResultsLoader { private: const string name_; const uchar delimiter_; const ushort separator_; const string srcFilePath_; bool checkStringForOptimalFResultsDeserializing(string &inputStr[]) const; ushort calculateCharCode(const uchar separator) const; public: COptimalFResultsLoader(const string srcFilePath, uchar separator); ~COptimalFResultsLoader(); double getOptimalLotsFor(const ulong magicNumber) const; double getOptimalFFor(const ulong magicNumber) const; double getBiggestLossFor(const ulong magicNumber) const; }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ COptimalFResultsLoader::COptimalFResultsLoader(const string srcFilePath = "/SRProject/results.csv", uchar separator = ','):name_("OptimalFResultsLoader"), srcFilePath_(srcFilePath), delimiter_(separator), separator_(calculateCharCode(separator)) { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ COptimalFResultsLoader::~COptimalFResultsLoader() { } //+------------------public------------------------------------------+ //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double COptimalFResultsLoader::getOptimalLotsFor(const ulong inputMagicNumber) const { double rsl = 0.0; CFileTxt* file = new CFileTxt(); int fileHandle = file.Open(srcFilePath_,FILE_READ|FILE_UNICODE|FILE_CSV); while (!FileIsEnding(fileHandle)) { string readString = file.ReadString(); string str[]; StringSplit(readString, separator_, str); if (checkStringForOptimalFResultsDeserializing(str)) { if (inputMagicNumber == (ulong)StringToInteger(str[0])) { rsl = StringToDouble(str[3]); } } } file.Close(); delete(file); return(rsl); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double COptimalFResultsLoader::getOptimalFFor(const ulong inputMagicNumber) const { double rsl = 0.0; CFileTxt* file = new CFileTxt(); int fileHandle = file.Open(srcFilePath_,FILE_READ|FILE_UNICODE|FILE_CSV); while (!FileIsEnding(fileHandle)) { string readString = file.ReadString(); string str[]; StringSplit(readString, separator_, str); if (checkStringForOptimalFResultsDeserializing(str)) { if (inputMagicNumber == (ulong)StringToInteger(str[0])) { rsl = StringToDouble(str[2]); } } } file.Close(); delete(file); return(rsl); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double COptimalFResultsLoader::getBiggestLossFor(const ulong inputMagicNumber) const { double rsl = 0.0; CFileTxt* file = new CFileTxt(); int fileHandle = file.Open(srcFilePath_,FILE_READ|FILE_UNICODE|FILE_CSV); while (!FileIsEnding(fileHandle)) { string readString = file.ReadString(); string str[]; StringSplit(readString, separator_, str); if (checkStringForOptimalFResultsDeserializing(str)) { if (inputMagicNumber == (ulong)StringToInteger(str[0])) { rsl = StringToDouble(str[1]); } } } file.Close(); delete(file); return(rsl); } //+---------------------private--------------------------------------+ //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool COptimalFResultsLoader::checkStringForOptimalFResultsDeserializing(string &inputStr[]) const { if (ArraySize(inputStr) < 4) { return(false); } return(true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ ushort COptimalFResultsLoader::calculateCharCode(const uchar separator) const { string str = CharToString(separator); return(StringGetCharacter(str,0)); } //+------------------------------------------------------------------+
