Files
2026-05-27 12:32:26 -04:00

187 lines
4.2 KiB
Plaintext

//+------------------------------------------------------------------+
//| MarketData.mqh - Market data wrapper |
//| Handles bid/ask, spread, symbol info, new bar detection |
//+------------------------------------------------------------------+
#ifndef __MARKETDATA_MQH__
#define __MARKETDATA_MQH__
#include "Config.mqh"
#include "Logger.mqh"
#include "Utilities.mqh"
class CMarketData
{
private:
string m_symbol;
CLogger *mp_logger;
datetime m_last_bar_time;
int m_digits;
double m_point;
public:
// Constructor
CMarketData(const string symbol, CLogger *logger)
{
m_symbol = symbol;
mp_logger = logger;
m_last_bar_time = 0;
m_digits = CUtilities::GetDigits(symbol);
m_point = CUtilities::GetPoint(symbol);
}
// Get current bid price
double GetBid() const
{
return SymbolInfoDouble(m_symbol, SYMBOL_BID);
}
// Get current ask price
double GetAsk() const
{
return SymbolInfoDouble(m_symbol, SYMBOL_ASK);
}
// Get current spread in points
int GetSpreadPoints() const
{
double spread_price = GetAsk() - GetBid();
return CUtilities::PriceToPoints(m_symbol, spread_price);
}
// Get current spread in price
double GetSpreadPrice() const
{
return GetAsk() - GetBid();
}
// Check if spread is acceptable
bool IsSpreadAcceptable(int max_spread_points) const
{
int current_spread = GetSpreadPoints();
if(current_spread > max_spread_points)
{
if(mp_logger)
{
// Build message without using variadic StringFormat to avoid parser issues
string msg = "Spread too wide: ";
msg += IntegerToString(current_spread);
msg += " > ";
msg += IntegerToString(max_spread_points);
mp_logger.Warning(msg);
}
return false;
}
return true;
}
// Detect new bar on current timeframe
bool IsNewBar()
{
datetime bar_time = iTime(m_symbol, PERIOD_CURRENT, 0);
if(m_last_bar_time == 0)
{
m_last_bar_time = bar_time;
return true;
}
if(bar_time != m_last_bar_time)
{
m_last_bar_time = bar_time;
return true;
}
return false;
}
// Get current close price
double GetClose() const
{
return iClose(m_symbol, PERIOD_CURRENT, 0);
}
// Get current open price
double GetOpen() const
{
return iOpen(m_symbol, PERIOD_CURRENT, 0);
}
// Get current high price
double GetHigh() const
{
return iHigh(m_symbol, PERIOD_CURRENT, 0);
}
// Get current low price
double GetLow() const
{
return iLow(m_symbol, PERIOD_CURRENT, 0);
}
// Get close price of bar N bars ago
double GetCloseAt(int shift) const
{
return iClose(m_symbol, PERIOD_CURRENT, shift);
}
// Get open price of bar N bars ago
double GetOpenAt(int shift) const
{
return iOpen(m_symbol, PERIOD_CURRENT, shift);
}
// Get symbol digits
int GetDigits() const
{
return m_digits;
}
// Get symbol point
double GetPoint() const
{
return m_point;
}
// Check if trading is allowed for this symbol
bool IsTradingAllowed() const
{
// Ensure symbol allows trading (full trade mode)
long trade_mode = (long)SymbolInfoInteger(m_symbol, SYMBOL_TRADE_MODE);
if(trade_mode != SYMBOL_TRADE_MODE_FULL)
return false;
// Basic check: ensure symbol is tradeable (has non-zero point and digits)
if(SymbolInfoDouble(m_symbol, SYMBOL_POINT) <= 0.0)
return false;
return true;
}
// Get symbol name
string GetSymbol() const
{
return m_symbol;
}
// Get minimum volume
double GetMinVolume() const
{
return SymbolInfoDouble(m_symbol, SYMBOL_VOLUME_MIN);
}
// Get maximum volume
double GetMaxVolume() const
{
return SymbolInfoDouble(m_symbol, SYMBOL_VOLUME_MAX);
}
// Get volume step
double GetVolumeStep() const
{
return SymbolInfoDouble(m_symbol, SYMBOL_VOLUME_STEP);
}
};
#endif //__MARKETDATA_MQH__