Анализ спреда по ценам Bid и Ask в MetaTrader 5
Введение
Если вы не используете лимитные и стоп-ордера для открытия и закрытия сделок, тогда сделки будут совершаться по рыночным ордерам. Цена, которую вы получаете в таком ордере, зависит от размера спреда.
Нажимая на кнопку покупки, вы по факту покупаете по цене спроса (Ask), которая на размер спреда выше цены предложения (Bid), на основе которой вы принимали решение о покупке.
Нажимая на кнопку продажи, вы по факту продаете по цене предложения (Bid), которая ниже цены спроса (Ask) на размер спреда.
Соответственно, нажимая на "Закрыть", чтобы закрыть открытую ранее позицию на покупку, вы фактически продаете по текущей цене бид.
И наоборот, при закрытии открытой ранее короткой позиции (на продажу), вы обратно выкупаете или перекрываете инструмент по текущей цене аск.
Тиковые данные в MetaTrader 5 позволяют проанализировать, какие же исторические значения спредов между ценами бид и аск были на самом деле.
При этом не нужно искать текущее значение спреда, потому что его можно получить через отображение линий цен бид и аск.
Давайте разбираться
Судя по этим графикам, брокер утверждает, что максимальные спреды при торговле равны 5 пунктам.
Если бы это было правдой, то полный цикл открытия и закрытия сделки стоил бы всего 1 пипс.
Таким образом, при совершении сделки с соотношением риска к прибыли 1/1, со стоп-лоссом в 10 пунктов и тейк-профитом в 10 пунктов, затраты для вас составили бы 10% от вашего риска/ставки.
Это достаточно справедливый спред. Например, букмекерские конторы обычно ставят 15%, а маржа прибыли в казино составляет около 4%.
Но на графике есть и вторая линия — она красного цвета. Это фактический средний спред, и он больше заявленного брокером спреда (черной пунктирной линии) почти в два раза, что подтверждается и в окне данных ниже. Поэтому в рассмотренном ранее примере с уровнями стоп-лосс и тейк-профит издержки для вас составят не менее двух пипсов, то есть уже 20%.
Более того, если вы торгуете скальперскими или похожими стратегиями с уровнями стоп-лосс и тейк-профит по 5 пипсов, или же если вы решите выйти раньше установленных стоп-уровней (при SL и TP по 10 пипсов), скажем, при убытке в 5 пипсов, издержки все равно составят те же 2 пипса. Но поскольку вы решили осторожно выйти, когда сделка начала идти против вас, издержки для вас теперь составят целых 40%.
Когда я только начинал торговать, я ставил стоп-лосс на уровне 5 пипсов и тейк-профит на 10, чтобы соотношение риска к прибыли было 2:1, (я полагаю, многие начинающие делают так). Понятно, что ничего хорошего из этого не вышло.
Поэтому я провел глубокий анализ графика EURUSD M1, используя надежный индикатор Zig Zag. Минимальный размер шага установил равным 5 пипсам, для меня это был приемлемый откат цены.
Результаты показали, что большинство небольших колебаний происходит в пределах 7 пипсов, тогда как шаг в 10 пипсов случается очень редко. Конечно, я учел все экономические публикации и волатильность рынка, поэтому результаты были получены в основном по средним показателям внутри торговых сессий.
После этого я начал устанавливать стоп-лосс равным 10 пипсам, а тейк-профит оставил открытым. Я хотел внимательно следить за сделкой и выходить из нее при достижении убытка или прибыли в 7 пипсов. Результаты уже стали лучше, но прибыли по-прежнему не было. И в тот момент я обратил внимание на высокие спреды у брокера, у которого торговал. Естественно, я начал искать лучшего брокера.
Если торговать на выходе новостей или при возросшей волатильности рынка, можно заметить, что фактический спред брокера вырастает до 15 пунктов, то есть в три раза от стандартных 5 пунктов. Это значит, что придется заплатить 3 пипса, или 60% от ставки.
И уж точно не стоит торговать после 20:30 по британскому времени (у меня 21:30 по времени сервера) — в это время спред может быть в 4, 5 и даже 6 раз выше. Особенно неприятен будет спред, если вы решите подержать позицию на выходных. На графике видно, что это спред почти в 10 раз превышает стандартные 5 пунктов. Такой спред может покрыть только экстремально большой уровень стоп-лосса или тейк-профита.
OnInit() Code example
#property indicator_separate_window #property indicator_buffers 2 #property indicator_plots 2 //--- plots #property indicator_label1 "ActSpread" #property indicator_type1 DRAW_LINE #property indicator_color1 clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 2 #property indicator_label2 "DeclaredSpread" #property indicator_type2 DRAW_LINE #property indicator_color2 clrBlack #property indicator_style2 STYLE_DASH #property indicator_width2 2 //--- Параметры индикатора input int numRecentBarsBack=100; //#RecentBarsBack M30+~100, M5~200, M1~500 input bool doPrint=true; //true=выводит данные в Инструменты\Журнал советника //--- Буферы индикатора double ActSpreadBuf[], DeclaredSpreadBuf[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { int numBars=iBars(_Symbol,PERIOD_CURRENT)-2; // Проверяем наличие необходимых данных для запроса перед началом if(numRecentBarsBack>numBars) { Alert("Не получится выполнить ", numRecentBarsBack, "! Доступно только ", numBars, " баров", " попробуйте около 100 для графиков старше 30 минут,", " 200 для 5-минутного, 500 для минутного.", " В противном случае индикатор будет работать медленно" ); return(INIT_PARAMETERS_INCORRECT); } double sumPrice=0; double avgPrice=0; // Получаем стандартный спред в 5 пунктов для стандартной валюты EURUSD double stdSpread=0.00005/iClose("EURUSD",PERIOD_M1,1); // 1.2 ~= EURUSD std price //Найдем текущую среднюю цену используемого инструмента, чтобы можно было определить стандартный спред и _Point int CheckAvgPriceBars=MathMin(numRecentBarsBack, 200); int i=0; for(; i<CheckAvgPriceBars; i++) { sumPrice+=iClose(_Symbol,PERIOD_CURRENT,i); } avgPrice=sumPrice/(i? i: 1.0); //преобразуем stdSpread в stdPoint - делим на 5, чтобы сравнивать яблоки с яблоками, а не апельсинами double stdPoint=StringToDouble(DoubleToString(avgPrice*stdSpread/5.0,6)); Print(i, "=bars done, avgPrice=", DoubleToString(avgPrice,6), " std=", DoubleToString(1.2*stdSpread, 6), " stdPoint=", DoubleToString(stdPoint, 6) ); SetIndexBuffer(0,ActSpreadBuf,INDICATOR_DATA); SetIndexBuffer(1,DeclaredSpreadBuf,INDICATOR_DATA); string indName ="BAS("+_Symbol; indName+=" TF="+string(_Period); indName+=" stdPoint="+DoubleToString(stdPoint, 6); indName+=") Last("+string(numRecentBarsBack)+") Bars"; IndicatorSetString(INDICATOR_SHORTNAME, indName); IndicatorSetInteger(INDICATOR_DIGITS,6); IndicatorSetDouble(INDICATOR_MINIMUM, 0.0); IndicatorSetInteger(INDICATOR_LEVELS, 20); //отмечаем каждый стандартный спред EURUSD в 5 пунктов, чтобы сравнить спред данной валюты с EURUSD IndicatorSetDouble(INDICATOR_LEVELVALUE,0, 0.000000); IndicatorSetDouble(INDICATOR_LEVELVALUE,1, 5*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,2, 10*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,3, 15*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,4, 20*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,5, 25*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,6, 30*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,7, 35*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,8, 40*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,9, 45*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,10,50*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,11,55*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,12,60*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,13,65*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,14,70*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,15,75*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,16,80*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,17,85*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,18,90*stdPoint); IndicatorSetDouble(INDICATOR_LEVELVALUE,19,95*stdPoint); return(INIT_SUCCEEDED); }
Это простой индикатор с двумя построениями. У него только два параметра. Один из них это 'numRecentBarsBack' — количество баров, которые необходимо проанализировать.
Первым делом в OnInit() проверяем, достаточно ли у нас данных для запроса. Если данных не хватает, сообщаем об этом пользователю и указываем более реалистичные значение. Завершаем индикатор с ошибкой.
Все остальное в OnInit() должно быть понятно. Единственно, что можно дополнительно отметить, это уровни, используемые в дополнительном окне индикатора — их значения соответствуют кратным стандартного спреда по EURUSD в 5 пунктов.
Это довольно важный шаг, потому что хотелось бы не только сравнить заявленные и фактические средние значения спреда, но и посмотреть спред различных валют в сравнении со стандартным спредом по паре EURUSD, которая традиционно имеет самый низкий спред из всех валют.
Получается довольно запутанный способ, потому что нужно получить текущую цену по EURUSD (и заменить 1.2 если ее нет), а затем разделить 5 пунктов по EURUSD на эту цену, чтобы построить график стандартного спреда. Затем перебираем numRecentBarsBack цен выбранного форекс-инструмента (я не проверял работу индикатора на нефорексных символах) и получаем среднюю цену этого инструмента.
Получив среднюю цену инструмента, можем построить график округленных стандартных пунктов, умножив среднюю цену инструмента на полученный ранее стандартный спред и разделив на 5 (стандартный спред в пунктах по EURUSD).
Затем полученные округленные стандартны пункты используем в значении каждого уровня. Также включаем в короткое название индикатора, как показано в названии индикатора на графике экзотика USDMXN ниже.
В примере USDMXN дневной спред заявлен в районе 0,0025, что равно примерно 3 уровням спреда выше нуля, что соответствует примерно 15 пунктам на графике EURUSD. Также обратите внимание, что фактический средний спред значительно превышает этот уровень у данного брокера.
На графике GBPAUD заявленный спред в дневное время показан в районе 0,00019, примерно 2,5 уровней спреда выше нуля, что сейчас равно примерное 12 пунктам на графике символа EURUSD. Также обратите внимание, что на этом графике фактические средние значения спреда довольно близки к заявленным значениям спреда от брокера.
На графике GBPJPY спред, заявленный брокером, находится районе 0,020, примерно 3 уровня спреда выше нуля, что примерно соответствует 15 пунктам на графике символа EURUSD. Также обратите внимание, что на этом графике фактические средние значения спреда довольно близки к заявленным значениям спреда от брокера.
Далее, на графике USDJPY заявленный дневной спред составляет около 0,0050, что примерно на уровень 1 спреда выше нуля, что соответствует примерно стандартным 5 пунктам на графике EURUSD. Также обратите внимание, что на этом графике фактические средние значения спреда примерно в два раза выше, чем заявленные значения спреда от брокера, так что сюда можно отнести сказанные выше комментарии о соотношении риска/прибыли по EURUSD.
Далее показаны еще несколько примеров — вы сами можете сделать выводы относительно соотношения уровней спреда.
Второй параметр в индикаторе — это значение bool 'doPrint', проверяемое в коде. Если значение true, выводим статистику по отдельным барам в лог советника, как показано в примере ниже. Индикатор может считаться медленнее, если указать слишком большое значение параметра 'numRecentBarsBack'. Поэтому по умолчанию выбрано 100 баров.
Если параметр 'doPrint' указан в значении true, а в параметре 'numRecentBarsBack' указано разумное значение, например около 100 на 30-минутном графике или 300 на минутном графике, тогда вы можете скопировать полученный журнал советника и отправить брокеру с доказательством фактических значений спреда.
OnCalculate() Code Example
//--- Глобальные переменные //--- Выбираем формат даты для вывода в журнал const uint dtFormat=uint(TIME_DATE|TIME_MINUTES); //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { //--- перед началом проверяем отсутствие данных или флаг Stop if(_StopFlag || rates_total<2) { Alert("Error, StopFlag=", _StopFlag, " #Bars=", rates_total); return(rates_total); } //показывает отчет только при начале или обновлении индикатора if(prev_calculated>2) { //если уже обнулили ActSpreadBuf, переходим к DeclaredSpreadBuf[] и возвращаемся. if(prev_calculated==rates_total) { int currBar=rates_total-1; DeclaredSpreadBuf[currBar]=spread[currBar]*_Point; return(rates_total); } // в противном случае это начало нового бара, поэтому обнуляем ActSpreadBuf else { int currBar=rates_total-1; ActSpreadBuf[currBar]=EMPTY_VALUE; return(rates_total); } } static int start=rates_total-numRecentBarsBack; MqlTick tickBuf[]; double sumSpread=0; double thisSpread=0; int ticks=0; int bid_tick=0; int ask_tick=0; int k=0; ArrayInitialize(ActSpreadBuf, EMPTY_VALUE); ArrayInitialize(DeclaredSpreadBuf, EMPTY_VALUE); for(int i=start; i<rates_total; i++) { sumSpread=0; thisSpread=0; bid_tick=0; ask_tick=0; k=0; ticks=CopyTicksRange(_Symbol, tickBuf, COPY_TICKS_INFO, // нужны только изменения бид и аск time[i-1]*1000, // время начала предыдущего бара time[i ]*1000 // время окончания предыдущего бара ); while(k<ticks) { if((tickBuf[k].flags&TICK_FLAG_ASK)==TICK_FLAG_ASK) ask_tick++; if((tickBuf[k].flags&TICK_FLAG_BID)==TICK_FLAG_BID) bid_tick++; sumSpread+=tickBuf[k].ask-tickBuf[k].bid; k++; } // проверить отсутствие ошибок деления на ноль при отсутствии тиковых данных if(ticks>0) { thisSpread=sumSpread/ticks; ActSpreadBuf[i-1]=thisSpread; } else { thisSpread=0.0; ActSpreadBuf[i-1]=EMPTY_VALUE; } DeclaredSpreadBuf[i-1]=spread[i-1]*_Point; if(doPrint) { Print(TimeToString(time[i-1], dtFormat), " NumTicks="+string(ticks), " b="+string(bid_tick), " a="+string(ask_tick), " AvgSpread=", DoubleToString(thisSpread/_Point, 1), " DeclaredSpread=", string(spread[i-1]) ); } } //не считаем статистику для неполного текущего бара, но можем сделать DeclaredSpread, если есть значение DeclaredSpreadBuf[rates_total-1]=(spread[rates_total-1]*_Point); //--- возвращаемое значение prev_calculated для следующего вызова return(rates_total); }
В приведенном выше примере OnCalculate() следует отметить использование CopyTicksRange() только для получения тиковых данных между началом бара/свечи предыдущего индекса и началом бара/свечи с текущим индексом. Также обратите внимание, что нам нужно преобразовать массив time[] в миллисекунды, умножив его на 1000, потому что данные datetime точны только с точностью до секунды, а CopyTicksRange() требует миллисекунды.
ticks=CopyTicksRange(_Symbol, tickBuf, COPY_TICKS_INFO, // нужны только изменения бид и аск time[i-1]*1000, // время начала предыдущего бара time[i ]*1000 // время окончания предыдущего бара );
Также обратите внимание, что индикатор собирает тики по бид и аск, хотя они не отображаются на графиках. Значение тиков бид должно совпадать со значением в массиве tick_volume[] — и оно совпадает, как видно в окне данных.
Примечание о загрузке тиков
Если хотите проверить инструмент, с которым обычно не работаете, надо добавить этот символ в Обзор Рынка через меню Вид \ Символы, дважды нажав на требуемый символ. В этом окне также надо перейти на вкладку тиков и запросить "Все тики" с даты примерно за месяц до текущей, которая указывается в первой дате в меню, а во втором окне даты следует указать завтрашнюю дату.
Заключение
Прежде чем начать торговать какой-либо валютой, надо понимать реальный уровень риска при использовании выбранного алгоритма (особенно важно при скальпинге, свинг-торговле и др.), и сравнить риски по разным валютам на основе общего стандартного размера спреда.
Из того, что удалось обнаружить мне, я бы рекомендовал трейдерам выбирать основные валюты, которые напрямую привязаны к доллару: USDCAD, USDCHF, USDJPY, EURUSD и GBPUSD. Именно они показали самые низкие спреды.
Также можно дать понять брокерам, что мы видим реальные спреды и можем заметить, когда значения спредов растут. Удачи! И не забывайте, что если не можете найти брокера с приемлемыми уровнями спреда для торговли в определенные часы, не торгуйте, потому что вы все равно не сможете получить прибыль!
Опережу ваши вопросы — алгоритм работает только в платформе MetaTrader 5, потому что в MetaTrader 4 нет тиковых данных. Вот вам еще одна причина, чтобы перейти на пятую версию платформы.
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/9804
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Дико извиняюсь, но почитайте ниже:
1. У любого брокера есть отдел маркетинга, который и рекламирует услуги компании, в том числе через максимально возможные низкие спреды. Не надо путать рекламу с реальным положением вещей. У маркетолога одна полезная функция для общества - обратить Ваше внимание; за качество они не отвечают.
2. Спред как разница между настроениями покупателей и продавцов сильно зависит от ликвидности рынка. Ликвидность же в свою очередь меняется в течении суток, и в зависимости от положения дел на рынке. Я видел, как usdjpy полгода в 2014 г стоял на месте, и спред там был достаточно расширенный. Нельзя было торговать вообще - цена плохо двигалась, и спред был в 2-3 раза выше, чем в 2012-13 годах. А затем к концу года начался неудержимый тренд, ликвидности хоть отбавляй, рынок ревел! Спред иногда достигал 1-2 пипса по 3 знаку (usdjpy). Что касается времени суток, то денег больше всего у американцев (США - финансовый центр планеты). Также на американскую сессию накладывается общая ликвидность Европы. Поэтому в это время спреды низкие, ликвидность высокая, все играют с азартом, рынок подвижен. Если торгуете внутри дня, то выбирайте исключительно американскую сессию.
3. Рыночный спред в один и тот же момент времени по одному и тому же инструменту не одинаков! Чем больший объём единовременно ты покупаешь или продаешь, тем худшую цену получаешь. Есть такое понятие как стакан цен. Обычно чем крупнее объём, тем выше разница цен между ними. А впритык торгуется мелочь. Эта мелочь и отображается в тиках, которые автор так скрупулёзно зачем то анализировал. Но эта мелочь не является самим рынком. Поэтому крупные инвестиционные фонды не покупают в одной сделке весь объём. Чтобы крупной рыбе войти в рынок, нужно ещё поработать, и обычно не один день. Крупнейшие игроки начинают скупать актив по мелочи у тех, кто торгует впритык, набирая последовательно позицию. И выходить им приходится тоже последовательно. А если горит у них, то происходит обвал или резкий взлёт вследствие быстрого выхода по любым приемлемым ценам. Так что крупным игрокам зачастую приходится платить больше по рыночным издержкам. Поэтому они всегда играют в масштабе от недели до квартала.
Дико извиняюсь, но почитайте ниже:
1. У любого брокера есть отдел маркетинга, который и рекламирует услуги компании, в том числе через максимально возможные низкие спреды. Не надо путать рекламу с реальным положением вещей. У маркетолога одна полезная функция для общества - обратить Ваше внимание; за качество они не отвечают.
2. Спред как разница между настроениями покупателей и продавцов сильно зависит от ликвидности рынка. Ликвидность же в свою очередь меняется в течении суток, и в зависимости от положения дел на рынке. Я видел, как usdjpy полгода в 2014 г стоял на месте, и спред там был достаточно расширенный. Нельзя было торговать вообще - цена плохо двигалась, и спред был в 2-3 раза выше, чем в 2012-13 годах. А затем к концу года начался неудержимый тренд, ликвидности хоть отбавляй, рынок ревел! Спред иногда достигал 1-2 пипса по 3 знаку (usdjpy). Что касается времени суток, то денег больше всего у американцев (США - финансовый центр планеты). Также на американскую сессию накладывается общая ликвидность Европы. Поэтому в это время спреды низкие, ликвидность высокая, все играют с азартом, рынок подвижен. Если торгуете внутри дня, то выбирайте исключительно американскую сессию.
3. Рыночный спред в один и тот же момент времени по одному и тому же инструменту не одинаков! Чем больший объём единовременно ты покупаешь или продаешь, тем худшую цену получаешь. Есть такое понятие как стакан цен. Обычно чем крупнее объём, тем выше разница цен между ними. А впритык торгуется мелочь. Эта мелочь и отображается в тиках, которые автор так скрупулёзно зачем то анализировал. Но эта мелочь не является самим рынком. Поэтому крупные инвестиционные фонды не покупают в одной сделке весь объём. Чтобы крупной рыбе войти в рынок, нужно ещё поработать, и обычно не один день. Крупнейшие игроки начинают скупать актив по мелочи у тех, кто торгует впритык, набирая последовательно позицию. И выходить им приходится тоже последовательно. А если горит у них, то происходит обвал или резкий взлёт вследствие быстрого выхода по любым приемлемым ценам. Так что крупным игрокам зачастую приходится платить больше по рыночным издержкам. Поэтому они всегда играют в масштабе от недели до квартала.
И за подобную статью платят 200 долларов ? Очень спорная философия.
У меня и ряда сигналов - другая. Исходя из того что мы покупаем по цене аск то на момент покупки нас интересует только эта цена. При закрытии это фактически сделка sell, поэтому нас интересует только цена bid. Не важно какие были цены , какие спреды. Если цена хороша, то надо торговать в соответствующую сторону.
Пример: Обычно в Ролловер спреды раздвигаются очень сильно и многие пары находятся во флете. В один прекрасный момент вы видите что цена аск очень ниже сформированного коридора. Покупаем, зная, что цена bid вернется к верху коридора, когда спреды восстановится. И в момент покупки нас цена Бид абсолютно не интересует.
Подобные стратегии вы увидите в сервисе сигналов.Где торговля ведется с 23 до 1 ночи. Кстати одни из самых стабильных. И даже повышенный спред не мешает зарабатывать стабильно.
Вот так на практике перечеркивается утверждение, что не нужно торговать на повышенном спреде.