← К каталогу
Исходный код · ID 3187

MTH Renko Chart Builder Indi Ver 02

!mth renko chart builder indi ver02.mq5
Вы автор или правообладатель?

Сообщите нам, если считаете, что материал размещён без разрешения.

Краткий обзор

О программе

Индикатор для MetaTrader 4, который строит офлайн-графики Renko, записывая исторические данные в файлы .hst. Он обрабатывает исторические свечи и текущие цены Bid, формируя ренко-боксы и сохраняя их в формате истории, который затем открывается как отдельный офлайн-график внутри терминала.

Поддерживаются два независимых Renko-графика с отдельными параметрами размера бокса, сдвига, таймфрейма, смещения, отображения фитилей и максимального количества баров. Для обновления окон графиков используется Windows API (PostMessageW), что требует разрешения на вызов DLL в настройках терминала.

Параметр StartingPrice позволяет начать построение Renko-графика с указанного ценового уровня, а не с текущей рыночной цены. Индикатор не содержит торговой логики и не использует торговые API.

Настройки программы

НастройкаОписание
StartingPrice Начальная цена — Начальная цена для построения Renko-графиков. Если текущая цена закрытия последнего бара выше этого значения, построение начинается от ближайшего бокса выше StartingPrice.
RenkoBoxSize1 Размер бокса 1 — Размер бокса первого Renko-графика в пунктах. При 5-значном котировании автоматически умножается на 10 или 100.
BoxShiftPercent1 Сдвиг боксов 1 — Процент сдвига боксов для первого Renko-графика. Определяет долю размера бокса, на которую сдвигается предыдущий бокс при пробитии уровня цены.
What time frame to use for the offline renko chart (RenkoTimeFrame1) Таймфрейм 1 — Таймфрейм первого офлайн Renko-графика. Определяет период, к которому привязывается создаваемый файл истории.
RenkoBoxOffset1 Смещение бокса 1 — Смещение боксов первого Renko-графика от начальной цены. Должно быть по модулю меньше размера бокса.
ShowWicks1 Показ фитилей 1 — Отображение фитилей (теней) на первом Renko-графике. Если включено, в бокс записываются экстремумы цены.
MaxBars1 Макс. баров 1 — Максимальное количество исторических баров, обрабатываемых при построении первого Renko-графика.
Use2ndRenkoChart Использовать 2-й Renko-график — Включение или отключение построения второго Renko-графика. При выключении строится только первый график.
RenkoBoxSize2 Размер бокса 2 — Размер бокса второго Renko-графика в пунктах. При 5-значном котировании автоматически умножается на 10 или 100.
BoxShiftPercent2 Сдвиг боксов 2 — Процент сдвига боксов для второго Renko-графика. Определяет долю размера бокса, на которую сдвигается предыдущий бокс при пробитии уровня цены.
What time frame to use for the offline renko chart (RenkoTimeFrame2) Таймфрейм 2 — Таймфрейм второго офлайн Renko-графика. Определяет период, к которому привязывается создаваемый файл истории.
RenkoBoxOffset2 Смещение бокса 2 — Смещение боксов второго Renko-графика от начальной цены. Должно быть по модулю меньше размера бокса.
ShowWicks2 Показ фитилей 2 — Отображение фитилей (теней) на втором Renko-графике. Если включено, в бокс записываются экстремумы цены.
MaxBars2 Макс. баров 2 — Максимальное количество исторических баров, обрабатываемых при построении второго Renko-графика.
EmulateOnLineChart Эмуляция обновления графика — Переключатель эмуляции обновления окон графиков через Windows API для автоматического перерисовывания офлайн-графиков.
StrangeSymbolName Сокращённое имя символа — Использовать сокращённое имя символа (первые 6 символов) при создании файлов истории офлайн-графиков.
Получить полный код

Поиск по коду файла

#property indicator_chart_window
#include <WinUser32.mqh>
#include <stdlib.mqh>

#import "user32.dll"
	int RegisterWindowMessageW(string lpString); 
   int GetWindowTextW(int hWnd,string lpString,int nMaxCount);
   int PostMessageW(int hWnd,int Msg,int wParam,int lParam);
#import

extern double  StartingPrice     = 161.001;

extern double  RenkoBoxSize1     = 5.0;
extern double  BoxShiftPercent1  = 100;
extern int     RenkoTimeFrame1   = 2;      // What time frame to use for the offline renko chart
extern int     RenkoBoxOffset1   = 0;
extern bool    ShowWicks1        = true;
extern int     MaxBars1          = 100000;

extern bool    Use2ndRenkoChart  = false;
extern double  RenkoBoxSize2     = 10.0;
extern double  BoxShiftPercent2  = 50;
extern int     RenkoTimeFrame2   = 3;      // What time frame to use for the offline renko chart
extern int     RenkoBoxOffset2   = 0;
extern bool    ShowWicks2        = true;
extern int     MaxBars2          = 10000;
extern bool    EmulateOnLineChart= true;
extern bool    StrangeSymbolName = false;

int HstHandle1 = -1, LastFPos1 = 0, MT4InternalMsg1 = 0;
int HstHandle2 = -1, LastFPos2 = 0, MT4InternalMsg2 = 0;
string SymbolName;

void UpdateChartWindow() {
	static int hwnd1 = 0;
	if(hwnd1 == 0) {
		hwnd1 = WindowHandle(SymbolName, RenkoTimeFrame1);
		if(hwnd1 != 0) Print("Chart window detected");
	}

	if(EmulateOnLineChart && MT4InternalMsg1 == 0) 
		MT4InternalMsg1 = RegisterWindowMessageW("MetaTrader4_Internal_Message");

	if(hwnd1 != 0) if(PostMessageW(hwnd1, WM_COMMAND, 0x822c, 0) == 0) hwnd1 = 0;
	if(hwnd1 != 0 && MT4InternalMsg1 != 0) PostMessageW(hwnd1, MT4InternalMsg1, 2, 1);

	static int hwnd2 = 0;
	if(hwnd2 == 0) {
		hwnd2 = WindowHandle(SymbolName, RenkoTimeFrame2);
		if(hwnd2 != 0) Print("Chart window detected");
	}

	if(EmulateOnLineChart && MT4InternalMsg2 == 0) 
		MT4InternalMsg2 = RegisterWindowMessageW("MetaTrader4_Internal_Message");

	if(hwnd2 != 0) if(PostMessageW(hwnd2, WM_COMMAND, 0x822c, 0) == 0) hwnd2 = 0;
	if(hwnd2 != 0 && MT4InternalMsg2 != 0) PostMessageW(hwnd2, MT4InternalMsg2, 2, 1);
	return;
}

int start() {
      // код доступен только после оплаты
   }

	static double BoxPoints1, UpWick1, DnWick1;
	static double PrevLow1, PrevHigh1, PrevOpen1, PrevClose1, CurVolume1, CurLow1, CurHigh1, CurOpen1, CurClose1;
	static datetime PrevTime1;
  		MqlRates rates;

	if(HstHandle1 < 0) {

		if(!IsDllsAllowed()) {
			Print("Error: Dll calls must be allowed!");
			return(-1);
		}		
		if(MathAbs(RenkoBoxOffset1) >= RenkoBoxSize1) {
			Print("Error: |RenkoBoxOffset| should be less then RenkoBoxSize1!");
			return(-1);
		}

		int BoxSize1 = RenkoBoxSize1;
		int BoxOffset1 = RenkoBoxOffset1;
		if(Digits == 5 || (Digits == 3 && StringFind(Symbol(), "JPY") != -1)) {
			BoxSize1 = BoxSize1*10;
			BoxOffset1 = BoxOffset1*10;
		}
		if(Digits == 6 || (Digits == 4 && StringFind(Symbol(), "JPY") != -1)) {
			BoxSize1 = BoxSize1*100;		
			BoxOffset1 = BoxOffset1*100;
		}

		if(StrangeSymbolName) SymbolName = StringSubstr(Symbol(), 0, 6);
		else SymbolName = Symbol();
		BoxPoints1 = NormalizeDouble(BoxSize1*Point, Digits);

      if (Close[Bars-1]>= StartingPrice)
         {
		   PrevLow1 = NormalizeDouble(BoxOffset1*Point + MathFloor((Close[Bars-1]-StartingPrice)/BoxPoints1)*BoxPoints1 + StartingPrice, Digits);
		   }

      if (Close[Bars-1]< StartingPrice)
         {
		   PrevLow1 = NormalizeDouble(BoxOffset1*Point +  StartingPrice - MathCeil((StartingPrice-Close[Bars-1])/BoxPoints1)*BoxPoints1 - Point, Digits);
		   }

		DnWick1 = PrevLow1;
		PrevHigh1 = PrevLow1 + BoxPoints1;
		UpWick1 = PrevHigh1;
		PrevOpen1 = PrevLow1;
		PrevClose1 = PrevHigh1;
		CurVolume1 = 1;
		PrevTime1 = Time[Bars-1];

		HstHandle1 = FileOpenHistory(SymbolName + (string)RenkoTimeFrame1 + ".hst", FILE_BIN|FILE_WRITE|FILE_ANSI);
		FileClose(HstHandle1); HstHandle1 = -1;
		HstHandle1 = FileOpenHistory(SymbolName + (string)RenkoTimeFrame1 + ".hst", FILE_BIN|FILE_READ|FILE_WRITE|FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_ANSI);

		if(HstHandle1< 0) {
			Print("Error: can\'t create / open history file: " + ErrorDescription(GetLastError()) + ": " + SymbolName + RenkoTimeFrame1 + ".hst");
			return(-1);
		}

		int HstUnused1[13];
		FileWriteInteger(HstHandle1, 401, LONG_VALUE); 			// Version
		FileWriteString(HstHandle1, "", 64);				// Copyright
		FileWriteString(HstHandle1, SymbolName, 12);			// Symbol
		FileWriteInteger(HstHandle1, RenkoTimeFrame1, LONG_VALUE);	// Period
		FileWriteInteger(HstHandle1, Digits, LONG_VALUE);		// Digits
		FileWriteInteger(HstHandle1, 0, LONG_VALUE);			// Time Sign
		FileWriteInteger(HstHandle1, 0, LONG_VALUE);			// Last Sync
		FileWriteArray(HstHandle1, HstUnused1, 0, 13);			// Unused

  		int i1 = Bars-2;
  			if (i1>MaxBars1) i1=MaxBars1; 

  		while(i1 >= 0) {

			CurVolume1 = CurVolume1 + Volume[i1];

			UpWick1 = MathMax(UpWick1, High[i1]);
			DnWick1 = MathMin(DnWick1, Low[i1]);

			bool UpTrend1 = High[i1]+Low[i1] > High[i1+1]+Low[i1+1];

			while(!UpTrend1 && (Low[i1] < PrevLow1-(BoxShiftPercent1/100)*BoxPoints1 || CompareDoubles(Low[i1], PrevLow1-(BoxShiftPercent1/100)*BoxPoints1))) {
  				PrevHigh1   =  PrevHigh1   -  (BoxShiftPercent1/100)* BoxPoints1;
  				PrevLow1    =  PrevLow1    -  (BoxShiftPercent1/100)*BoxPoints1;
  				PrevOpen1   =  PrevHigh1;
  				PrevClose1  =  PrevLow1;

            rates.time = PrevTime1;
            rates.open = PrevOpen1;
            rates.low  = PrevLow1;
            if(ShowWicks1 && UpWick1 > PrevHigh1)
                  rates.high = UpWick1;
            else  rates.high = PrevHigh1;             
            rates.close = PrevClose1;
            rates.real_volume = (long)CurVolume1;
            rates.tick_volume = (long)CurVolume1;
   				FileWriteStruct(HstHandle1,rates);

				UpWick1 = 0;
				DnWick1 = EMPTY_VALUE;
				CurVolume1 = 0;
				CurHigh1 = PrevLow1;
				CurLow1 = PrevLow1;  

				if(PrevTime1 < Time[i1]) PrevTime1 = Time[i1];
				else PrevTime1++;
			}

			while(High[i1] > PrevHigh1+(BoxShiftPercent1/100)*BoxPoints1 || CompareDoubles(High[i1], PrevHigh1+(BoxShiftPercent1/100)*BoxPoints1)) {
  				PrevHigh1   =  PrevHigh1   +  (BoxShiftPercent1/100)*BoxPoints1;
  				PrevLow1    =  PrevLow1    +  (BoxShiftPercent1/100)*BoxPoints1;
  				PrevOpen1   =  PrevLow1;
  				PrevClose1  =  PrevHigh1;

            rates.time = PrevTime1;
            rates.open = PrevOpen1;
            rates.high = PrevHigh1;
            if(ShowWicks1 && DnWick1 < PrevLow1)
                  rates.low = DnWick1;
            else  rates.low = PrevLow1;             
            rates.close = PrevClose1;
            rates.real_volume = (long)CurVolume1;
            rates.tick_volume = (long)CurVolume1;
   				FileWriteStruct(HstHandle1,rates);

				UpWick1 = 0;
				DnWick1 = EMPTY_VALUE;
				CurVolume1 = 0;
				CurHigh1 = PrevHigh1;
				CurLow1 = PrevHigh1;  

				if(PrevTime1 < Time[i1]) PrevTime1 = Time[i1];
				else PrevTime1++;
			}

			while(UpTrend1 && (Low[i1] < PrevLow1-(BoxShiftPercent1/100)*BoxPoints1 || CompareDoubles(Low[i1], PrevLow1-(BoxShiftPercent1/100)*BoxPoints1))) {
  				PrevHigh1   =  PrevHigh1   -  (BoxShiftPercent1/100)*BoxPoints1;
  				PrevLow1    =  PrevLow1    -  (BoxShiftPercent1/100)*BoxPoints1;
  				PrevOpen1   =  PrevHigh1;
  				PrevClose1  =  PrevLow1;

            rates.time = PrevTime1;
            rates.open = PrevOpen1;
            rates.low  = PrevLow1;
            if(ShowWicks1 && UpWick1 > PrevHigh1)
                  rates.high = UpWick1;
            else  rates.high = PrevHigh1;             
            rates.close = PrevClose1;
            rates.real_volume = (long)CurVolume1;
            rates.tick_volume = (long)CurVolume1;
   				FileWriteStruct(HstHandle1,rates);

				UpWick1 = 0;
				DnWick1 = EMPTY_VALUE;
				CurVolume1 = 0;
				CurHigh1 = PrevLow1;
				CurLow1 = PrevLow1;  

				if(PrevTime1 < Time[i1]) PrevTime1 = Time[i1];
				else PrevTime1++;
			}		
			i1--;
		} 
		LastFPos1 = FileTell(HstHandle1);   // Remember Last pos in file

		if(Close[0] > MathMax(PrevClose1, PrevOpen1)) CurOpen1 = MathMax(PrevClose1, PrevOpen1);
		else if (Close[0] < MathMin(PrevClose1, PrevOpen1)) CurOpen1 = MathMin(PrevClose1, PrevOpen1);
		else CurOpen1 = Close[0];

		CurClose1 = Close[0];

		if(UpWick1 > PrevHigh1) CurHigh1 = UpWick1;
		if(DnWick1 < PrevLow1) CurLow1 = DnWick1;

            rates.time = PrevTime1;
            rates.open = CurOpen1;
            rates.low  = CurLow1;
            rates.high = CurHigh1;             
            rates.close = CurClose1;
            rates.real_volume = (long)CurVolume1;
            rates.tick_volume = (long)CurVolume1;
   				FileWriteStruct(HstHandle1,rates);

		FileFlush(HstHandle1);

		UpdateChartWindow();

		return(0);

	} 		

	UpWick1 = MathMax(UpWick1, Bid);
	DnWick1 = MathMin(DnWick1, Bid);

	CurVolume1++;   			
	FileSeek(HstHandle1, LastFPos1, SEEK_SET);

   	if(Bid > PrevHigh1+(BoxShiftPercent1/100)*BoxPoints1 || CompareDoubles(Bid, PrevHigh1+(BoxShiftPercent1/100)*BoxPoints1)) {
		PrevHigh1    =  PrevHigh1   +  (BoxShiftPercent1/100)*BoxPoints1;
		PrevLow1     =  PrevLow1    +  (BoxShiftPercent1/100)*BoxPoints1;
		PrevOpen1    =  PrevLow1;
		PrevClose1   =  PrevHigh1;

            rates.time = PrevTime1;
            rates.open = PrevOpen1;
            rates.high = PrevHigh1;
            if(ShowWicks1 && DnWick1 < PrevLow1)
                  rates.low = DnWick1;
            else  rates.low = PrevLow1;             
            rates.close = PrevClose1;
            rates.real_volume = (long)CurVolume1;
            rates.tick_volume = (long)CurVolume1;
   				FileWriteStruct(HstHandle1,rates);

      	FileFlush(HstHandle1);
  	  	LastFPos1 = FileTell(HstHandle1);   // Remember Last pos in file				  							

		if(PrevTime1 < TimeCurrent()) PrevTime1 = TimeCurrent();
		else PrevTime1++;

  		CurVolume1 = 0;
		CurHigh1 = PrevHigh1;
		CurLow1 = PrevHigh1;  

		UpWick1 = 0;
		DnWick1 = EMPTY_VALUE;		

		UpdateChartWindow();				            		
  	}

	else if(Bid < PrevLow1-(BoxShiftPercent1/100)*BoxPoints1 || CompareDoubles(Bid,PrevLow1-(BoxShiftPercent1/100)*BoxPoints1)) {
  		PrevHigh1  =  PrevHigh1   -  (BoxShiftPercent1/100)*BoxPoints1;
  		PrevLow1   =  PrevLow1    -  (BoxShiftPercent1/100)*BoxPoints1;
  		PrevOpen1  =  PrevHigh1;
  		PrevClose1 =  PrevLow1;

            rates.time = PrevTime1;
            rates.open = PrevOpen1;
            rates.low  = PrevLow1;
            if(ShowWicks1 && UpWick1> PrevHigh1)
                  rates.high = UpWick1;
            else  rates.high = PrevHigh1;             
            rates.close = PrevClose1;
            rates.real_volume = (long)CurVolume1;
            rates.tick_volume = (long)CurVolume1;
   				FileWriteStruct(HstHandle1,rates);

      	FileFlush(HstHandle1);
  	  	LastFPos1 = FileTell(HstHandle1);   // Remember Last pos in file				  							

		if(PrevTime1 < TimeCurrent()) PrevTime1 = TimeCurrent();
		else PrevTime1++;      	

  		CurVolume1 = 0;
		CurHigh1 = PrevLow1;
		CurLow1 = PrevLow1;  

		UpWick1 = 0;
		DnWick1 = EMPTY_VALUE;		

		UpdateChartWindow();						
     	} 

	else {
		if(Bid > CurHigh1) CurHigh1 

Показано первые 50% кода (символов: 16518)

Открыть по тарифу

Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.

Разовая покупка файла

На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.

Чтобы оформить заказ, введите email и перейдите к оплате.

Стоимость полного кода
1 651,80₽ ≈ $20.19