Skip to content

Data Provider

The Data Provider is the heart of market data access in PyEventBT. It abstracts the complexity of data sourcing, seamlessly switching between historical CSV files for backtesting and real-time MetaTrader 5 feeds for live trading.

Unified API

A single API for both historical and live data. No code changes required to go live.

Multi-Timeframe

Access data from multiple timeframes simultaneously (e.g., trade on H1 while checking trends on D1).

Auto-Management

Handles data loading, caching, and updates automatically, so you can focus on strategy logic.

Indicator Ready

Returns data structures perfect for computing technical indicators like ATR, RSI, or Moving Averages.

In your strategy, the data provider is accessible via the modules object.

Retrieve a sequence of historical bars, useful for calculating indicators or analyzing trends.

@strategy.custom_signal_engine(...)
def my_strategy(event: BarEvent, modules: Modules):
# Get the last 50 bars for H1 timeframe
bars = modules.DATA_PROVIDER.get_latest_bars(
symbol=event.symbol,
timeframe=StrategyTimeframes.ONE_HOUR,
N=50
)
if bars is None or bars.height < 50:
return [] # Not enough data yet
# Access data columns
closes = bars.select('close').to_numpy()
highs = bars.select('high').to_numpy()

Here are practical examples of how to use the Data Provider in real trading scenarios.

  1. Request Bars: Fetch enough history to calculate your longest moving average.
  2. Calculate Indicators: Compute the Fast and Slow SMAs.
  3. Generate Signal: Compare the values to determine entries.
def ma_crossover_logic(symbol, modules):
# 1. Request Data (need at least 30 bars for the slow SMA)
bars = modules.DATA_PROVIDER.get_latest_bars(
symbol,
StrategyTimeframes.ONE_HOUR,
50
)
if bars is None or bars.height < 30: return
# 2. Calculate Indicators
closes = bars.select('close').to_numpy().flatten()
sma_fast = closes[-10:].mean() # 10-period
sma_slow = closes[-30:].mean() # 30-period
# 3. Logic
if sma_fast > sma_slow:
# Bullish condition
pass

Combine data from different timeframes to confirm trends.

# Entry Timeframe: 1 Hour
hourly_bars = modules.DATA_PROVIDER.get_latest_bars(
symbol, StrategyTimeframes.ONE_HOUR, 20
)
# Trend Timeframe: 1 Day
daily_bars = modules.DATA_PROVIDER.get_latest_bars(
symbol, StrategyTimeframes.ONE_DAY, 20
)
# Check if daily trend is UP before taking hourly buy signals
daily_closes = daily_bars.select('close').to_numpy()
is_uptrend = daily_closes[-1] > daily_closes[-5] # Simple trend check

The Data Provider abstracts the source, but it’s helpful to know where data comes from.

Reads from CSV files in your configured csv_dir. File structure is expected to be simple:

  • Directorydata/
    • EURUSD.csv
    • GBPUSD.csv
    • SPX500.csv

CSV Format: datetime,open,high,low,close,volume

Connects directly to the MetaTrader 5 terminal.

  • Real-time ticks: Updates bid/ask instantly.
  • Bar generation: Aggregates ticks into bars automatically.
  • Performance: Request only the N bars you need for your calculation. Fetching 1000 bars when you only need 14 for an RSI calculation is inefficient.
  • Safety: Use get_latest_bid/ask for execution logic to ensure you are trading at the most current price, rather than the close of the last bar.

Here is the complete list of methods available in the DATA_PROVIDER module.

Returns the most recent N bars for a given symbol and timeframe.

def get_latest_bars(self, symbol: str, timeframe: str, N: int) -> Bars
ParameterTypeDescription
symbolstrThe instrument symbol (e.g., “EURUSD”).
timeframestrThe timeframe (e.g., StrategyTimeframes.ONE_HOUR).
NintNumber of bars to retrieve.

Returns: A Bars object containing the requested history.

Returns the single latest completed bar.

def get_latest_bar(self, symbol: str, timeframe: str) -> Bar

Returns: A single Bar object representing the most recent completed period.

Returns the most recent tick data (Real-time).

def get_latest_tick(self, symbol: str) -> dict

Returns: A dictionary matching the MT5 Tick structure (bid, ask, last, volume, time).

Returns the absolute latest bid price.

def get_latest_bid(self, symbol: str) -> Decimal

Returns the absolute latest ask price.

def get_latest_ask(self, symbol: str) -> Decimal

Returns the timestamp of the last data point.

def get_latest_datetime(self, symbol: str, timeframe: str) -> Timestamp