Market data ingestion
Skill mahmoud20138/Tradecraft/plugins/tradecraft/skills/market-data-ingestion
102 Claude Code skills across 7 categories -- trading strategies, Azure, VSCode extensions, AI prompts, and custom automation skills
npx -y skills add mahmoud20138/Tradecraft --skill market-data-ingestionAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 7 stars7 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Market data ingestion pipelines: OHLCV data fetching from MT5, yfinance, Alpha Vantage, data cleaning, normalization, missing bar handling, multi-symbol batch fetching. USE FOR: market data, OHLCV, fetch data, download data, historical data, MT5 data, yfinance, Alpha Vantage, data pipeline, data ingestion, price data, candle data, bar data, multi-symbol, batch fetch, data cleaning, normalize prices.
SKILL.md
4.0 KB, as published. Nobody here has run it
Skill: Market Data Ingestion | Domain: trading | Category: data | Level: intermediate Tags:
trading,data,ingestion,mt5,ohlcv,batch
Market Data Ingestion
MT5 Data Fetcher (Primary — your setup)
import MetaTrader5 as mt5
import pandas as pd
from datetime import datetime
def fetch_mt5(symbol: str, timeframe: int, bars: int = 1000) -> pd.DataFrame:
"""Fetch OHLCV from MT5. Timeframe: mt5.TIMEFRAME_M5, H1, D1, etc."""
mt5.initialize()
rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, bars)
mt5.shutdown()
if rates is None:
raise ValueError(f"No data for {symbol}")
df = pd.DataFrame(rates)
df["time"] = pd.to_datetime(df["time"], unit="s")
df.set_index("time", inplace=True)
df.rename(columns={"open":"open","high":"high","low":"low",
"close":"close","tick_volume":"volume"}, inplace=True)
return df[["open","high","low","close","volume"]]
def fetch_multi_mt5(symbols: list, timeframe: int, bars: int = 500) -> dict:
"""Batch fetch multiple symbols from MT5."""
mt5.initialize()
data = {}
for sym in symbols:
rates = mt5.copy_rates_from_pos(sym, timeframe, 0, bars)
if rates is not None:
df = pd.DataFrame(rates)
df["time"] = pd.to_datetime(df["time"], unit="s")
df.set_index("time", inplace=True)
data[sym] = df[["open","high","low","close","tick_volume"]].rename(
columns={"tick_volume": "volume"})
mt5.shutdown()
return data
Your 23 Watched Symbols
WATCHED = [
"XAUUSDm","XAGUSDm","EURUSDm","GBPUSDm","USDJPYm","AUDUSDm","USDCADm","USDCHFm",
"BTCUSDm","ETHUSDm","USOILm","USTECm","US500m","US30m",
"TSLAm","AAPLm","MSFTm","NVDAm","AMZNm","GOOGm","METAm","JPMm","BAm"
]
TIMEFRAMES = {
"M5": mt5.TIMEFRAME_M5, "M15": mt5.TIMEFRAME_M15,
"H1": mt5.TIMEFRAME_H1, "H4": mt5.TIMEFRAME_H4, "D1": mt5.TIMEFRAME_D1,
}
Data Cleaning Pipeline
def clean_ohlcv(df: pd.DataFrame, max_gap_bars: int = 5) -> pd.DataFrame:
"""Remove bad bars, fill small gaps, validate OHLC logic."""
# Drop bars where OHLC relationship is broken
df = df[(df["high"] >= df["low"]) &
(df["high"] >= df["open"]) & (df["high"] >= df["close"]) &
(df["low"] <= df["open"]) & (df["low"] <= df["close"])]
# Drop zero-volume bars (market closed)
df = df[df["volume"] > 0]
# Forward-fill small gaps (weekend gaps etc.)
df = df.resample("1min").asfreq()
gap_size = df["close"].isna().rolling(max_gap_bars + 1).sum()
df = df[gap_size <= max_gap_bars].ffill()
return df.dropna()
yfinance Fallback (for research/backtesting)
import yfinance as yf
def fetch_yf(ticker: str, period: str = "1y", interval: str = "1d") -> pd.DataFrame:
"""Fetch from Yahoo Finance. interval: 1m,5m,15m,1h,1d,1wk."""
df = yf.download(ticker, period=period, interval=interval, auto_adjust=True, progress=False)
df.columns = [c.lower() for c in df.columns]
return df[["open","high","low","close","volume"]]