period_converter_shift
Download scriptOverview
This script is designed for traders using the MetaTrader platform who need to analyze price data on a different time scale than what they are currently viewing. Specifically, it automates the process of "aggregating" or combining smaller price movements into larger, custom-defined periods and saving that organized data into a dedicated history file.
Core Functionality
The script performs three primary actions: scaling, aggregating, and recording.
1. Custom Period Scaling Instead of relying on standard timeframes (like 1-minute or 5-minute charts), the tool allows you to define a "Multiplier." For example, if you are viewing a 1-minute chart but want to see what the data looks like for every 3 minutes, the script calculates that specific larger timeframe automatically. It also includes a "Time Shift" feature, allowing you to offset the starting point of the data analysis by a specific number of hours.
2. Data Aggregation Logic The script looks at the raw price history and begins grouping individual bars together based on your chosen multiplier. It follows a specific logic to ensure the aggregated data is accurate:
- Open Price: It captures the opening price of the first minute in the new period.
- High & Low Prices: It scans every small movement within that period to identify the highest peak and the lowest valley reached.
- Closing Price: It identifies the final price at the end of the period.
- Volume: It sums up all the trading volume from the smaller bars into a single total for the larger period.
3. Automatic File Generation Once the script calculates these values, it creates a new history file on your system. It writes out a structured record containing the timestamp, the aggregated open, high, low, close (OHLC) prices, and the total volume. This allows you to have a clean, custom-sized data set ready for use without having to manually calculate those figures or wait for the platform to generate them.
Real-Time Updating
The script does not just run once and stop; it remains active while the market is open. It constantly monitors incoming price "ticks" (the smallest updates of price movement).
- It identifies when a new bar in your custom timeframe is about to complete.
- As the current bar progresses, it updates the temporary high, low, and volume totals.
- Once the period is finished, it writes the completed data to the file and immediately begins collecting data for the next period.
Summary of Benefits
For a non-technical user, this means you can effectively "zoom out" from your current chart. If the platform doesn't offer the specific timeframe you need for your strategy, this script builds that timeframe for you, saves it to a file, and keeps it updated in real-time as the market moves.
//+------------------------------------------------------------------+
//| Period_Converter.mq4 |
//| Copyright © 2005, MetaQuotes Software Corp. |
//| http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, MetaQuotes Software Corp."
#property link "http://www.metaquotes.net"
#property show_inputs
#include <WinUser32.mqh>
extern int ExtPeriodMultiplier=3; // new period multiplier factor
extern int TimeShift=0; //Hours of shift
int ExtHandle=-1;
//+------------------------------------------------------------------+
//| script program start function |
//+------------------------------------------------------------------+
int start()
{
int i, start_pos, i_time, time0, last_fpos, periodseconds;
double d_open, d_low, d_high, d_close, d_volume, last_volume;
int hwnd=0,cnt=0;
//---- History header
int version=400;
string c_copyright;
string c_symbol=Symbol();
int i_period=Period()*ExtPeriodMultiplier;
int i_digits=Digits;
int i_unused[13];
//----
ExtHandle=FileOpenHistory(c_symbol+i_period+".hst", FILE_BIN|FILE_WRITE);
if(ExtHandle < 0) return(-1);
//---- write history file header
c_copyright="(C)opyright 2003, MetaQuotes Software Corp.";
FileWriteInteger(ExtHandle, version, LONG_VALUE);
FileWriteString(ExtHandle, c_copyright, 64);
FileWriteString(ExtHandle, c_symbol, 12);
FileWriteInteger(ExtHandle, i_period, LONG_VALUE);
FileWriteInteger(ExtHandle, i_digits, LONG_VALUE);
FileWriteInteger(ExtHandle, 0, LONG_VALUE); //timesign
FileWriteInteger(ExtHandle, 0, LONG_VALUE); //last_sync
FileWriteArray(ExtHandle, i_unused, 0, 13);
//---- write history file
periodseconds=i_period*60;
start_pos=Bars-1;
d_open=Open[start_pos];
d_low=Low[start_pos];
d_high=High[start_pos];
d_volume=Volume[start_pos];
//---- normalize open time
i_time=(Time[start_pos]+TimeShift*3600)/periodseconds;
i_time*=periodseconds;
for(i=start_pos-1;i>=0; i--)
{
time0=Time[i]+TimeShift*3600;
if(time0>=i_time+periodseconds || i==0)
{
if(i==0 && time0<i_time+periodseconds)
{
d_volume+=Volume[0];
if (Low[0]<d_low) d_low=Low[0];
if (High[0]>d_high) d_high=High[0];
d_close=Close[0];
}
last_fpos=FileTell(ExtHandle);
last_volume=Volume[i];
FileWriteInteger(ExtHandle, i_time, LONG_VALUE);
FileWriteDouble(ExtHandle, d_open, DOUBLE_VALUE);
FileWriteDouble(ExtHandle, d_low, DOUBLE_VALUE);
FileWriteDouble(ExtHandle, d_high, DOUBLE_VALUE);
FileWriteDouble(ExtHandle, d_close, DOUBLE_VALUE);
FileWriteDouble(ExtHandle, d_volume, DOUBLE_VALUE);
FileFlush(ExtHandle);
cnt++;
if(time0>=i_time+periodseconds)
{
i_time=time0/periodseconds;
i_time*=periodseconds;
d_open=Open[i];
d_low=Low[i];
d_high=High[i];
d_close=Close[i];
d_volume=last_volume;
}
}
else
{
d_volume+=Volume[i];
if (Low[i]<d_low) d_low=Low[i];
if (High[i]>d_high) d_high=High[i];
d_close=Close[i];
}
}
FileFlush(ExtHandle);
Print(cnt," record(s) written");
//---- collect incoming ticks
int last_time=LocalTime()+TimeShift*3600-5;
while(IsStopped()==false)
{
int cur_time=LocalTime()+TimeShift*3600;
//---- check for new rates
if(RefreshRates())
{
time0=Time[0]+TimeShift*3600;
FileSeek(ExtHandle,last_fpos,SEEK_SET);
//---- is there current bar?
if(time0<i_time+periodseconds)
{
d_volume+=Volume[0]-last_volume;
last_volume=Volume[0];
if (Low[0]<d_low) d_low=Low[0];
if (High[0]>d_high) d_high=High[0];
d_close=Close[0];
}
else
{
//---- no, there is new bar
d_volume+=Volume[1]-last_volume;
if (Low[1]<d_low) d_low=Low[1];
if (High[1]>d_high) d_high=High[1];
//---- write previous bar remains
FileWriteInteger(ExtHandle, i_time, LONG_VALUE);
FileWriteDouble(ExtHandle, d_open, DOUBLE_VALUE);
FileWriteDouble(ExtHandle, d_low, DOUBLE_VALUE);
FileWriteDouble(ExtHandle, d_high, DOUBLE_VALUE);
FileWriteDouble(ExtHandle, d_close, DOUBLE_VALUE);
FileWriteDouble(ExtHandle, d_volume, DOUBLE_VALUE);
last_fpos=FileTell(ExtHandle);
//----
i_time=time0/periodseconds;
i_time*=periodseconds;
d_open=Open[0];
d_low=Low[0];
d_high=High[0];
d_close=Close[0];
d_volume=Volume[0];
last_volume=d_volume;
}
//----
FileWriteInteger(ExtHandle, i_time, LONG_VALUE);
FileWriteDouble(ExtHandle, d_open, DOUBLE_VALUE);
FileWriteDouble(ExtHandle, d_low, DOUBLE_VALUE);
FileWriteDouble(ExtHandle, d_high, DOUBLE_VALUE);
FileWriteDouble(ExtHandle, d_close, DOUBLE_VALUE);
FileWriteDouble(ExtHandle, d_volume, DOUBLE_VALUE);
FileFlush(ExtHandle);
//----
if(hwnd==0)
{
hwnd=WindowHandle(Symbol(),i_period);
if(hwnd!=0) Print("Chart window detected");
}
//---- refresh window not frequently than 1 time in 2 seconds
if(hwnd!=0 && cur_time-last_time>=2)
{
PostMessageA(hwnd,WM_COMMAND,33324,0);
last_time=cur_time;
}
}
}
//----
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void deinit()
{
if(ExtHandle>=0) { FileClose(ExtHandle); ExtHandle=-1; }
}
//+------------------------------------------------------------------+
Comments