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

!MTH Renko Chart Builder Indi Ver 03_new_nmc

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

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

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

О программе

Индикатор «!MTH Renko Chart Builder» строит офлайн-графики типа Renko на платформе MetaTrader 5. Он обрабатывает исторические и текущие тиковые данные, формирует свечные бары Renko и записывает их в файлы истории (.hst), которые затем отображаются как офлайн-чарты.

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

Для обновления офлайн-окна используются системные сообщения Windows (PostMessageW / RegisterWindowMessageW), поэтому для работы требуется разрешение на вызов DLL. Индикатор корректирует размер ящика в зависимости от количества знаков после запятой у инструмента (3, 4, 5 или 6 цифр).

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

НастройкаОписание
StartingPrice Стартовая цена для запуска обработки Renko-баров; если равна 0, рассчитывается автоматически по минимуму за MaxBars
RenkoBoxSize1 Размер ящика в пунктах для первого Renko-графика
BoxShiftPercent1 Процент сдвига ящика для первого Renko-графика, используемый для уменьшения шума при построении баров
RenkoTimeFrame1 Таймфрейм для первого офлайн Renko-графика (например, M2 = 2)
RenkoBoxOffset1 Смещение ящика для первого Renko-графика, должно быть меньше по модулю чем RenkoBoxSize1
ShowWicks1 Отображение фитилей (максимум/минимум) на первом Renko-графике
MaxBars1 Максимальное количество баров исторических данных для обработки первым Renko-графиком
Use2ndRenkoChart Включает второй Renko-график с отдельными параметрами размера, сдвига и таймфрейма
RenkoBoxSize2 Размер ящика в пунктах для второго Renko-графика
BoxShiftPercent2 Процент сдвига ящика для второго Renko-графика, используемый для уменьшения шума при построении баров
RenkoTimeFrame2 Таймфрейм для второго офлайн Renko-графика (например, M3 = 3)
RenkoBoxOffset2 Смещение ящика для второго Renko-графика, должно быть меньше по модулю чем RenkoBoxSize2
ShowWicks2 Отображение фитилей (максимум/минимум) на втором Renko-графике
MaxBars2 Максимальное количество баров исторических данных для обработки вторым Renko-графиком
EmulateOnLineChart Включает эмуляцию обновления офлайн-графика через системные сообщения Windows на текущем графике
StrangeSymbolName Использовать сокращённое имя символа (первые 6 символов) при создании офлайн-графика
Получить полный код

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

#property version   "1.00"
#property strict

#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       =  0;

extern int      RenkoBoxSize1       =  10;

extern double   BoxShiftPercent1    = 15;

extern int      RenkoTimeFrame1   = 2;     
extern int      RenkoBoxOffset1   = 0;
extern bool     ShowWicks1        = true;
extern int      MaxBars1          = 5000; 
extern bool     Use2ndRenkoChart  = false;  
extern int      RenkoBoxSize2     = 20;
extern double   BoxShiftPercent2  = 15;
extern int      RenkoTimeFrame2   = 3;
extern int      RenkoBoxOffset2   = 0;
extern bool     ShowWicks2        = true;
extern int      MaxBars2          = 5000;

extern bool     EmulateOnLineChart= true;
extern bool     StrangeSymbolName = true;

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

string SymbolName;
string symbol;

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

void UpdateChart1_Window()
{

	static int hwnd1 = 0;
	if(hwnd1 == 0) {
		hwnd1 = WindowHandle(SymbolName, RenkoTimeFrame1); 

		if(hwnd1 != 0) Print("Chart window ",hwnd1," found");
	}

	if(EmulateOnLineChart && MT4InternalMsg1 == 0) 
		MT4InternalMsg1 = RegisterWindowMessageW("MetaTrader4_Internal_Message");  //setup an Internal_Message channel for this mt4 chart

	if(hwnd1 != 0) if(PostMessageW(hwnd1, WM_COMMAND, 0x822c, 0) == 0) hwnd1 = 0; //wake up chart1 window 
	if(hwnd1 != 0 && MT4InternalMsg1 != 0) PostMessageW(hwnd1, MT4InternalMsg1, 2, 1);  //send message

	return;
}

void UpdateChart2_Window()
{

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

	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 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[])
  {
      // код доступен только после оплаты
   }

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

  	MqlRates rates;   //copy time series data 

	if(HstHandle1 < 0) 
	{

	   StartingPrice = Low[iLowest(symbol,0,MODE_LOW,MaxBars1,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);//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 + IntegerToString(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);

		UpdateChart1_Window();

		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;		

		UpdateChart1_Window();				            		
  	}

	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 = 

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

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

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

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

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

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

Стоимость полного кода
1 700,40₽ ≈ $20.78