А цены открытия Buy и Sell хранить в переменных (ну и стопы с тейк/профитами).
Вопрос разработчикам: в МТ3 размер маржи по открытию 1 лота по любой валютной паре при бэк-тестинге всегда равен 1000$. В МТ4 это будет считаться более правильно или так и останется?
Будет считаться правильно, но с оговорками:
dBalance = dBalance + 100 * (Low[nBar] - dOpenPrice - 5 * Point) * dLotSize;
Здесь
else if(nType == 1 && High[nBar] >= dStop) // If SELL and stop loss reached
тоже спред
надо
else if(nType == 1 && High[nBar] >= dStop-5*Point) // If SELL and stop loss reached
тоже спред
И вообще, если стоплосс фиксированный в 150 пунктов, зачем вычислять размер лося, надо просто отнимать от Balance это количество пунктов.
Пока все
> И вообще, если стоплосс фиксированный в 150 пунктов, зачем вычислять размер лося, надо просто отнимать от Balance это количество пунктов.
Ну, это ведь общая стратегия. Может быть, кто-то будет динамически менять стоп лосс...
Спасибо за помощь.
С уважением,
Кварк
Я таким образом проверил парочку стратегий еще в "ранних" билдах. Идея рабочая в принципе. Советовать ничего не буду, просто поделюсь "наработанными" наблюдениями. На примере длинной позиции. Если условия срослись на каком-то баре, открываемся на следующем баре по цене Low+spread (=Ask). Закрываемся на баре, на котором срослись условия, по цене Low. Эти уровни запоминаются в двух переменных, разница между которыми даёт профит в пунктах. Деньги считать не надо и баланс тоже, в принципе не нужен (и связанные со всем этим проверки). В файле получается общий профит в пунктах +350 или -540, т.е. сразу всё становится ясно. В файл записывается ДатаВремя, тип (buy,sell), валюта, уровень открытия, уровень закрытия, профит в пунктах. Получается очень простой для анализа в Excel'e файл. И достаточно близко к реалиям. Одну стратегию я проверял неделю на демо, потом этот же кусок истории "прогнал" таким вот образом. Расхождения в 1-3 пункта по сделке. Да и тело программы-индикатора-тестера получается довольно простым и компактным. Есть только один момент, за которым надо последить. Поскольку тестер работает со статичной историей, он может открываться и закрываться лучше, чем на живом рынке - проскальзывание. Поэтому в индикаторе надо специально ухудшать условия. Т.е., например, добавить пару пунктов к уровню открытия, убрать пару пунктов от уровня закрытия.
Также, мне кажется, честнее и открываться и закрываться на следующем баре.
Если условия срослись на каком-то баре, открываемся на следующем баре по цене Low+spread (=Ask). Эти уровни запоминаются в двух переменных, разница между которыми даёт профит в пунктах. Деньги считать не надо и баланс тоже, в принципе не нужен (и связанные со всем этим проверки). В файле получается общий профит в пунктах +350 или -540, т.е. сразу всё становится ясно.
Проходили, знаем. Очень четко заметна разница: работаем по текущему бару - есть профит, например, 500pt. Пробуем работать по следующему бару - сразу почти такой же убыток, например, -500pt. Это к вопросу о важности момента принятия решения. А вот насчет проскальзывания - если работать по следующему бару хотя бы на часовике - проскальзывание вряд ли ощутишь - большинство сделок пройдут нормально. С другй стороны, часовой бар пунктов в 50 - не редкость и ждать его завершения для принятия решения не всегда правильно. Не грааль, в общем, будем искать...
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
При тестировании используется худшая возможная цена, что снимает вопрос "где брать внутренние цены бара".
Подразумевается, что каждый вписывает свои несколько строчек логики тестера, та стратегия, которую я использовал в этом примере, прибыльной не является - это всего лишь пример.
Индикатор генерирует файл (test.txt) с отчетом, пользуясь к-л программой (например, Эксель), можно построить график прибыли, также рассчитывается дродаун.
Заранее спасибо за критику :)
Кварк
#property copyright "Copyright Quark" #property link "" #property indicator_separate_window #property indicator_buffers 2 #property indicator_color1 Aqua #property indicator_color2 Red #property indicator_minimum -1 #property indicator_maximum 1 string strReportFileName = "test.txt"; // indicator buffers double arrBuyBuffer[]; // Buy indicator line double arrSellBuffer[]; // Sell indicator line // For example, if we use Ma14 and Clv21, it should be at least 21. // Here I use 30, which is guaranteed to be larger than delays, // produced by indicators I use. int nRemoveFirst = 30; double dStopLoss = 150; // points // Stochastic indicator double dStochMain; double dStochSignal; double dStochMainPrev; double dStochSignalPrev; // Balance (total amount of money and securities) double dBalance; double dLotSize = 100; // 0.1 lot int nType = 0; // -1 buy, 1 sell, 0 - none // Open price of the last order. Important: this (simple) implementation // does not allow more than one order in a time double dOpenPrice; // dStop = dOpenPrice +/- dStopLoss * Point; double dStop; //////////////////////// int init() { // When we buy, we draw a blue bar down, when we sell, // we draw a red bar up. SetIndexStyle(0, DRAW_HISTOGRAM); SetIndexShift(0, 0); SetIndexStyle(1, DRAW_HISTOGRAM); SetIndexShift(1, 0); IndicatorDigits(4); IndicatorShortName("Tester"); // indicator buffers mapping SetIndexBuffer(0, arrBuyBuffer); SetIndexBuffer(1, arrSellBuffer); SetIndexDrawBegin(0, nRemoveFirst); SetIndexDrawBegin(1, nRemoveFirst); return(0); } /////////////////////////// int deinit() { } /////////////////// int start() { dBalance = 1000; // Initial amount for testing 1000$ // How many bars were processed int nExtCountedBars = IndicatorCounted(); // It is not a "real" indicator, we only calculate it once, // when all data are uncounted and have to be updated if(nExtCountedBars != 0) return(-1); FileDelete(strReportFileName); int hFile = FileOpen(strReportFileName, FILE_WRITE, ';'); string str = "Number Operation Price Closed ClosePrice Total"; FileWrite(hFile, str); bool bStop; // A position was closed by a stop loss double dMaxDrawDown = 0; // Max. Drawdown double dCurrentMax = dBalance; // Used to calculate drawdown int nTradeNumber = 0; for(int nBar = Bars - nRemoveFirst; nBar > 0; nBar--) { dStochMain = iStochastic(NULL,0,10,6,6,MODE_SMA,1, MODE_MAIN,nBar); dStochSignal = iStochastic(NULL,0,10,6,6,MODE_SMA,1, MODE_SIGNAL,nBar); dStochMainPrev = iStochastic(NULL,0,10,6,6,MODE_SMA,1, MODE_MAIN,nBar+1); dStochSignalPrev = iStochastic(NULL,0,10,6,6,MODE_SMA,1, MODE_SIGNAL,nBar+1); arrBuyBuffer[nBar] = 0; // Set to "no buy, no sell" arrSellBuffer[nBar] = 0; if(nType != 0) // If we have an open order { bStop = false; double dClosedAt; if(nType == -1 && Low[nBar] <= dStop) // If BUY and stop loss reached { // Close position at the worse possible price // 100 is a leverage. dBalance = dBalance + 100 * (Low[nBar] - dOpenPrice - 5 * Point) * dLotSize; bStop = true; dClosedAt = Low[nBar]; } else if(nType == 1 && High[nBar] >= dStop) // If SELL and stop loss reached { dBalance = dBalance + 100 * (dOpenPrice - High[nBar] - 5 * Point) * dLotSize; bStop = true; dClosedAt = High[nBar]; } if(bStop == true) { nType = 0; // No more open positions str = str + "Stop " + dClosedAt + " " + dBalance; FileWrite(hFile, str); } } double dDrawDown = (dCurrentMax - dBalance) / dCurrentMax; dMaxDrawDown = MathMax(dMaxDrawDown, dDrawDown); dCurrentMax = MathMax(dCurrentMax, dBalance); // Logic of the trading system begins // If it is time to buy if(nType != -1 // no long positions && dStochMainPrev <= dStochSignalPrev && dStochMain >= dStochSignal && dStochMainPrev < 5) { if(nType == 1) // If we have short - close it { dBalance = dBalance + 100 * (dOpenPrice - High[nBar] - 5 * Point) * dLotSize; str = str + "Close " + High[nBar] + " " + dBalance; FileWrite(hFile, str); } arrBuyBuffer[nBar] = -1; dOpenPrice = High[nBar]; dStop = dOpenPrice - dStopLoss * Point; nType = -1; str = nTradeNumber + " Buy " + High[nBar] + " "; nTradeNumber++; } // Time to sell else if(nType != 1 // no short positions && dStochSignalPrev <= dStochMainPrev && dStochSignal >= dStochMain && dStochMainPrev > 95) { if(nType == -1) { dBalance = dBalance + 100 * (Low[nBar] - dOpenPrice - 5 * Point) * dLotSize; str = str + "Close " + Low[nBar] + " " + dBalance; FileWrite(hFile, str); } arrSellBuffer[nBar] = 1; dOpenPrice = Low[nBar]; dStop = dOpenPrice + dStopLoss * Point; nType = 1; str = nTradeNumber + " Sell " + Low[nBar] + " "; nTradeNumber++; } } // If at the end we have open positions, close them if(nType == 1) { dBalance = dBalance + 100 * (dOpenPrice - High[1] - 5 * Point) * dLotSize; str = str + "Close " + High[nBar] + " " + dBalance; FileWrite(hFile, str); } else if(nType == -1) { dBalance = dBalance + 100 * (Low[1] - dOpenPrice - 5 * Point) * dLotSize; str = str + "Close " + Low[nBar] + " " + dBalance; FileWrite(hFile, str); } str = "Balance: " + dBalance + ", Max. Drawdown: " + dMaxDrawDown + ", Number of trades: " + nTradeNumber; FileWrite(hFile, str); Comment("Balance: ", dBalance); FileClose(hFile); return(0); } ///////////////////