Optimal F Service
- Utilitários
- Semen Racheev
- Versão: 1.0
- Ativações: 10
Serviço Ótimo F
- Tipo de Aplicação: Serviço
- Funções da Aplicação: Cálculo da fração ótima e do volume de operação para alcançar o crescimento máximo da curva de capital, com base nos resultados de operações anteriores.
Sobre esta aplicação
A gestão de capital é o componente mais crucial e frequentemente subestimado de qualquer sistema de trading. Uma gestão adequada pode melhorar — e em alguns casos significativamente — o desempenho do seu algoritmo de trading.
Esta aplicação calcula automaticamente a fração ótima e o volume de operação utilizando o algoritmo proposto por Ralph Vince no livro "The Mathematics of Money Management", para alcançar o crescimento geométrico máximo do saldo da conta. Este ponto é único para qualquer sistema de trading e é essencial conhecê-lo. Nos seus sistemas de trading, nunca use um tamanho de operação que exceda o valor ótimo!
Os algoritmos de gestão de capital NÃO são projetados para sistemas matematicamente perdedores baseados em médias, martingale ou estratégias similares. Esses sistemas serão filtrados pela aplicação antes de realizar cálculos, pois a fração ótima e o volume de operação para esses sistemas são sempre iguais a zero. Os algoritmos de gestão de capital podem melhorar os resultados SOMENTE para sistemas de trading matematicamente rentáveis (aqueles com expectativa matemática positiva). Portanto, este serviço é recomendado APENAS para profissionais que entendem o que estão fazendo.
Além disso, o algoritmo não considera correlações (dependências) entre sistemas que operam simultaneamente. Para que o algoritmo funcione de forma eficaz, é necessário um conjunto bem diversificado de sistemas de trading.
Como usar
Parâmetros:
- LOG_LEVEL - Nível de registro para a seção de Especialistas do terminal. DEBUG fornece informações mais detalhadas, enquanto ERROR registra o mínimo.
- MAGIC_LIST - Lista separada por vírgulas de identificadores de sistemas (Magic Numbers) que operam simultaneamente e requerem cálculos.
- TRADE_FILES_PATH - Caminho para o diretório contendo os arquivos com os resultados das operações anteriores (relativo a <Pasta de Dados>/MQL5/Files/).
- OUTPUT_FILE_PATH - Caminho para o arquivo onde os resultados dos cálculos serão salvos (relativo a <Pasta de Dados>/MQL5/Files/).
- WORK_PERIOD - Frequência dos recálculos em segundos.
- BALANCE_MATRIX_PERIOD - Período sobre o qual os resultados são agregados, com cálculos baseados nesse período agregado em vez de cada operação individual.
Antes do primeiro uso сada sistema de trading deve ser testado no testador de estratégias até o momento atual. Recomenda-se selecionar um período de tempo que inclua pelo menos 100 operações. Use o Test Trade Saver Script e siga as instruções para extrair os arquivos de resultados dos testes (*.tst) no formato exigido.
Se o sistema de trading já tiver sido usado no terminal e houver posições no histórico com o MAGIC especificado, você deve configurar um parâmetro CUSTOM_MAGIC_NUMBER diferente no script!
Depois para garantir que os arquivos de dados sejam atualizados regularmente, execute o Trade Saver Service seguindo as instruções.
Após a exportação inicial de dados dos testes com o Trade Saver Script, o Trade Saver Service atualizará continuamente os arquivos com novos dados à medida que estiverem disponíveis, enquanto o Optimal F Service calculará e gravará regularmente novos valores no arquivo de resultados.
Algoritmo
- Extraia a lista de sistemas que requerem cálculos do parâmetro MAGIC_LIST.
- Use arquivos de texto chamados <MAGIC>.csv no formato <MAGIC>,<POSITION_CLOSE_TIME>,<LOTS>,< RESULT_$> contendo os resultados das operações anteriores do diretório especificado por TRADE_FILES_PATH.
- Construa uma matriz para a função da curva de saldo, onde cada valor a[i][j] representa o resultado do sistema de trading i para o período j.
- Verifique cada sistema quanto a pelo menos um período negativo nos seus resultados. Se um sistema não tiver períodos negativos, exclua-o dos cálculos posteriores (esses sistemas devem ser removidos).
- Avalie a expectativa matemática de cada sistema. Se um sistema não tiver valor esperado positivo, exclua-o dos cálculos posteriores (esses sistemas devem ser removidos).
- Determine a margem de erro necessária para calcular o volume de operação com precisão de 0,01.
- Para cada sistema restante, calcule sua fração ótima.
- Divida o saldo atual em partes iguais para os sistemas restantes. Para cada sistema e seu saldo alocado, calcule o volume de operação em lotes correspondente à fração ótima.
- Grave os resultados no arquivo de texto especificado por OUTPUT_FILE_PATH no formato <MAGIC>,<BIGGEST_LOSS>,<OPTIMAL_F>,<OPTIMAL_LOTS>.
Links e referências
- Ralph Vince - The Mathematics of Money Management: Risk Analysis Techniques for Traders (ISBN-13: 978-0471547389)
Para desenvolvedores
Você pode usar a seguinte classe para integrar os resultados nos seus sistemas 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)); } //+------------------------------------------------------------------+
