Offline charts -> learning how to create one

 

So bear with me.

When I run the following code, I get an offline chart but when I open the offline chart, all I get is a "waiting for update".  Anyone know why?

I know, I'm just copying EURUSD data, but like I said; I'm learning.

The sub class:

//+------------------------------------------------------------------+
//|                                                  FileHistory.mqh |
//|                                 Copyright 2021, Nondisclosure007 |
//|                                              https://no.link.yet |
//+------------------------------------------------------------------+
#include "FileBin.mqh"
//+------------------------------------------------------------------+
//| Opening a history file                                           |
//+------------------------------------------------------------------+
class CFileHistory : public CFileBin
  {
public:
                     CFileHistory(void);
                    ~CFileHistory(void);
   //--- methods of access to protected data
   int               OpenHistory(const string file_name);
   uint              WriteIntegerHistory(const int value);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CFileHistory::CFileHistory(void)
  {
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CFileHistory::~CFileHistory(void)
  {
  }
//+------------------------------------------------------------------+
//| Opening a binary file                                            |
//+------------------------------------------------------------------+
int CFileHistory::OpenHistory(const string file_name)
  {
//--- check handle
   if(m_handle!=INVALID_HANDLE)
      Close();
   const int open_flags=FILE_BIN|FILE_WRITE|FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_ANSI;
   m_handle=FileOpenHistory(file_name+".hst",open_flags);
   if(m_handle!=INVALID_HANDLE)
     {
      m_flags|=open_flags;
      m_name=file_name;
     }
   return(m_handle);
  }
//+------------------------------------------------------------------+
//| Overload: FileWriteInteger for history files                     |
//+------------------------------------------------------------------+
uint CFileHistory::WriteIntegerHistory(const int value)
  {
//--- check handle
   if(m_handle!=INVALID_HANDLE)
      return(FileWriteInteger(m_handle,value,LONG_VALUE));
//--- failure
   return(0);
  }
//+------------------------------------------------------------------+

The code of the indicator:

//+------------------------------------------------------------------+
//|                                                Currency LIVE.mq4 |
//|                                 Copyright 2021, Nondisclosure007 |
//|                                              https://no.link.yet |
//| Indicator draws nothing.  Creates chart
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, Nondisclosure007"
#property link      "https://no.link.yet"
#property version   "1.00"
#property strict
#property indicator_chart_window

input string inpCurrency = "USD";

#include <Files\FileHistory.mqh>

CFileHistory oFile;

datetime cur_time, last_time; //time0;
ulong    last_fpos = 0;
//long     last_volume = 0;
//int      i,start_pos,periodseconds;
//int      cnt = 0;
//---- History header
int      file_version = 401;
string   c_copyright = "Copyright 2021, Nondisclosure007";
string   c_symbol = Symbol();
int      i_period = Period();
int      i_digits = Digits;
int      i_unused[13];
MqlRates rate, curr;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   int handle = oFile.OpenHistory(inpCurrency);
   if(handle < 0)
     {
      Print("Opening USD failed!  Not initialized!");
      return(INIT_FAILED);
     }
   ArrayInitialize(i_unused,0);
//--- write history file header
   oFile.WriteInteger(file_version);   // FileWriteInteger(ExtHandle,file_version,LONG_VALUE);
   oFile.WriteString(c_copyright,64);  // FileWriteString(ExtHandle,c_copyright,64);
   oFile.WriteString("USD",12);        // FileWriteString(ExtHandle,c_symbol,12);
   oFile.WriteInteger(i_period);       // FileWriteInteger(ExtHandle,i_period,LONG_VALUE);
   oFile.WriteInteger(i_digits);       // FileWriteInteger(ExtHandle,i_digits,LONG_VALUE);
   oFile.WriteInteger(0);              // FileWriteInteger(ExtHandle,0,LONG_VALUE);
   oFile.WriteInteger(0);              // FileWriteInteger(ExtHandle,0,LONG_VALUE);
   oFile.WriteArray(i_unused,0,13);    // FileWriteArray(ExtHandle,i_unused,0,13);
   cur_time = TimeLocal();
   last_time = TimeLocal();
//---
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---
   cur_time = TimeLocal();
   int i,limit;
   limit = rates_total - prev_calculated;
   if(prev_calculated > 0)
     {
      limit++;
     }
   string sym = "EURUSD";
   int ibarshift = 0;
   for(i = 0; i < limit; i++)
     {
      ibarshift = iBarShift(sym,0,Time[i],true);
      if(ibarshift < 0)
        {
         // might need to '0' out rate here.
         continue;
        }
      rate.close = iClose(sym,0,ibarshift);
      rate.high = iHigh(sym,0,ibarshift);
      rate.low = iLow(sym,0,ibarshift);
      rate.open = iOpen(sym,0,ibarshift);
      rate.tick_volume = iVolume(sym,0,ibarshift);
      rate.time = iTime(sym,0,ibarshift);
      rate.real_volume = 0;
      rate.spread = 0;
      oFile.WriteStruct(rate);
      oFile.Flush();
     }
   long chart_id = 0;
//--- target chart is not found yet. it can be opened via Main menu - File - Open offline
   if(chart_id == 0)
     {
      long id = ChartFirst();
      while(id >= 0)
        {
         //--- find appropriate offline chart
         if(ChartSymbol(id) == inpCurrency && ChartGetInteger(id,CHART_IS_OFFLINE))
           {
            chart_id = id;
            ChartSetInteger(chart_id,CHART_AUTOSCROLL,true);
            ChartSetInteger(chart_id,CHART_SHIFT,true);
            ChartNavigate(chart_id,CHART_END);
            ChartRedraw(chart_id);
            PrintFormat("Chart window [%s,%d] found",inpCurrency);
            break;
           }
         //--- enumerate opened charts
         id = ChartNext(id);
        }
     }
//--- refresh window not frequently than 1 time in 2 seconds
   if(chart_id != 0 && cur_time - last_time >= 2)
     {
      ChartRedraw(chart_id); //ChartSetSymbolPeriod(chart_id,Symbol(),i_period);
      last_time = cur_time;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

Yes, I "borrowed" from period converter.

Target is MT4.

 

I've shortened the code a little.  

It creates the chart, and I can open it and see it.  But the data is all wrong and it doesn't constantly update.  Can anyone assist?

//+------------------------------------------------------------------+
//|                                                Currency LIVE.mq4 |
//|                                 Copyright 2021, Nondisclosure007 |
//|                                              https://no.link.yet |
//| Indicator draws nothing.  Creates chart  Constant "Waiting for update"
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, Nondisclosure007"
#property link      "https://no.link.yet"
#property version   "1.00"
#property strict
#property indicator_chart_window


#include <winuser32.mqh>
#include <stdlib.mqh>
#include <stderror.mqh>
#include <Files\FileHistory.mqh>
#include <Charts\Chart.mqh>

CFileHistory oFile;
CChart oChart;

MqlRates        rateinfo;
int                     hwnd = 0;

//--- input parameters
input string   inpCurrency = "USD";
input int   inpPeriod   = 3;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
        int             ver = 401;
        string  cr = "copyleft";
        string  symbol = "USD";
        int             digits = Digits;
        int             unused[13];
   int hf = oFile.OpenHistory(inpCurrency+IntegerToString(inpPeriod));
   if(hf < 0)
     {
      Print("Opening USD failed!  Not initialized!");
      return(INIT_FAILED);
     }
   if(oFile.Size() <=0)
     {
      oFile.WriteInteger(ver);   
      oFile.WriteString(cr,64);  
      oFile.WriteString(symbol,12);
      oFile.WriteInteger(inpPeriod);
      oFile.WriteInteger(digits); 
      oFile.WriteInteger(0); 
      oFile.WriteInteger(0); 
      oFile.WriteArray(unused,0,13); 
     }
        else // go to end of existing history file
        {
                oFile.Seek(0, SEEK_END);
        }
        long chartid = 0;
        if ((chartid = oChart.Open(symbol,0)) == 0) 
           {
            Print("Init failed!");
            return(INIT_FAILED);
           }
        hwnd = (int)oChart.GetInteger(CHART_WINDOW_HANDLE); //,0);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---
   int i,limit;
   limit = rates_total - prev_calculated;
   if(prev_calculated > 0)
     {
      limit++;
     }
   string sym = "EURUSD";
   int ibarshift = 0;
   for(i = 0; i < limit; i++)
     {
      GetRates(sym,i);
      oFile.WriteStruct(rateinfo);
      oFile.Flush();
     }
   PostMessageA(hwnd, WM_COMMAND, 33324, 0);
   return(rates_total);
  }
//+------------------------------------------------------------------+

void OnDeinit(const int reason)
{
        oFile.Close();
        oChart.Close();
}

void GetRates(string sym, int index)
{
   rateinfo.close = iClose(sym,0,index);
   rateinfo.high = iHigh(sym,0,index);
   rateinfo.low = iLow(sym,0,index);
   rateinfo.open = iOpen(sym,0,index);
   rateinfo.spread = (int)SymbolInfoInteger(sym,SYMBOL_SPREAD);
   rateinfo.tick_volume = iVolume(sym,0,index);
   rateinfo.time = iTime(sym,0,index);
}
Reason: