diff --git a/README.md b/README.md index bb56ee1..33e292e 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,32 @@ result = mbt.run(strategy, config, store) print(result.summary()) ``` +## Loading data + +Bring your own data, or pull it from a built-in connector — both return a +`DataStore` ready for `mbt.run(...)`. + +**CSV** — free on all tiers, auto-detects standard / MetaTrader 4 / MetaTrader 5: + +```python +store = mbt.import_csv("EURUSD_1m.csv", symbol="EURUSD", symbol_id=1, + interval="1m", asset_class="forex") +``` + +**Exchange connectors** — Binance, Hyperliquid, dYdX, Bitstamp (free); Databento, Massive (Pro): + +```python +store = mbt.ingest(provider="binance", symbol="BTCUSDT", symbol_id=1, + start="2024-01-01T00:00:00Z", end="2025-01-01T00:00:00Z") +``` + +Or from the CLI: + +```bash +manifoldbt import-csv data.csv --symbol EURUSD --symbol-id 1 --interval 1m +manifoldbt ingest --provider binance --symbol BTCUSDT --symbol-id 1 --start ... --end ... +``` + ## Examples | # | Example | What it shows | @@ -86,6 +112,13 @@ print(result.summary()) | 09 | [3D Surface](examples/09_surface_3d.py) | Parameter surface plot | | 10 | [Monte Carlo](examples/10_monte_carlo.py) | Permutation-based robustness | | 11 | [Portfolio](examples/11_portfolio.py) | Multi-strategy portfolio | +| 12 | [Diagnostics](examples/12_diagnostics.py) | Lookahead & exposure safety checks | +| 13 | [Stochastic Simulation](examples/13_stochastic_simulation.py) | SDE path simulation (GBM, Heston, …) | +| 14 | [Multi-Timeframe](examples/14_multi_timeframe.py) | Combining signals across timeframes | +| 15 | [Cross-Exchange](examples/15_cross_exchange.py) | Signal on one venue, execute on another | +| 16 | [Exogenous Data](examples/16_hashrate_exogene.py) | External series (e.g. hashrate) as a signal | +| 17 | [Per-Venue Fees](examples/17_per_venue_fees.py) | Per-venue funding & borrow costs | +| 18 | [CSV Import](examples/18_csv_import.py) | Load OHLCV from CSV (standard / MT4 / MT5) | ## Performance diff --git a/examples/18_csv_import.py b/examples/18_csv_import.py new file mode 100644 index 0000000..2f363c0 --- /dev/null +++ b/examples/18_csv_import.py @@ -0,0 +1,72 @@ +"""CSV Import -- load your own OHLCV data from a CSV file. + +Demonstrates: + - bt.import_csv() -- auto-detects standard / MetaTrader 4 / MetaTrader 5 + - Backtesting on the imported data, exactly like a built-in connector + - Free on all tiers (no Pro license required) + +The standard format is a header row + `timestamp,open,high,low,close,volume` +where timestamp is Unix milliseconds. MT4/MT5 exports are auto-detected. + +Usage: + python examples/18_csv_import.py +""" +import os +import tempfile + +import manifoldbt as mbt +from manifoldbt.indicators import close, ema +from manifoldbt.helpers import time_range, Interval + +# -- 1. A sample CSV ---------------------------------------------------------- +# In practice you'd point `import_csv` straight at your own file. Here we +# synthesize a small one so the example runs out of the box. +tmp = tempfile.mkdtemp() +csv_path = os.path.join(tmp, "SAMPLE_1m.csv") + +base_ms = 1_704_067_200_000 # 2024-01-01 00:00 UTC +px = 100.0 +with open(csv_path, "w") as f: + f.write("timestamp,open,high,low,close,volume\n") + for i in range(3000): + ts = base_ms + i * 60_000 # 1-minute bars + nxt = px * (1.0 + (0.0009 if i % 3 else -0.0007)) + hi = max(px, nxt) + 0.05 + lo = min(px, nxt) - 0.05 + f.write(f"{ts},{px:.4f},{hi:.4f},{lo:.4f},{nxt:.4f},{1000 + i}\n") + px = nxt + +# -- 2. Import into the store (free, all tiers) ------------------------------- +store = mbt.import_csv( + csv_path, + symbol="SAMPLE", + symbol_id=1, + interval="1m", + data_root=os.path.join(tmp, "data"), + metadata_db=os.path.join(tmp, "meta.sqlite"), + asset_class="crypto_spot", +) +print("Imported:", store.list_symbols()) + +# -- 3. Backtest on it like any other data ------------------------------------ +strategy = ( + mbt.Strategy.create("ema_cross") + .signal("fast", ema(close, 10)) + .signal("slow", ema(close, 30)) + .size(mbt.when(ema(close, 10) > ema(close, 30), 0.5, 0.0)) + .describe("EMA(10/30) crossover on CSV-imported data") +) + +start, end = time_range("2024-01-01", "2024-01-04") +config = mbt.BacktestConfig( + universe=[1], + time_range_start=start, + time_range_end=end, + bar_interval=Interval.minutes(1), + initial_capital=10_000, + warmup_bars=30, +) + +if __name__ == "__main__": + result = mbt.run(strategy, config, store) + print(result.summary())