From f2769cbc434d5afd58545256d363e88abc25a883 Mon Sep 17 00:00:00 2001 From: "Cody (Radius Red)" Date: Thu, 26 Mar 2026 16:57:55 +0000 Subject: [PATCH] docs: align documentation with live public API - Update README.md with correct install flow, public package surface, and Dukascopy-cache backtest entry points - Fix stale module paths across aggregation_guide, backtesting_guide, metrics_guide, risk_management, and strategy_guide Co-Authored-By: Paperclip --- README.md | 32 +++++++++++++++++----- docs/aggregation_guide.md | 8 +++--- docs/backtesting_guide.md | 57 ++++++++++++++++++++++++++++----------- docs/metrics_guide.md | 14 +++++----- docs/risk_management.md | 10 +++---- docs/strategy_guide.md | 3 +-- 6 files changed, 85 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 4882510..afc1eea 100644 --- a/README.md +++ b/README.md @@ -61,12 +61,12 @@ Backtesting uses the same event model as live trading. High-level flow: -- CSV or historical provider feeds market data -- Backtest runner drives event loop -- Strategy executes normally +- Dukascopy cache data is loaded via `BacktestClient.from_dukascopy_cache(...)` +- `run_backtest(...)` drives the event loop and recording pipeline +- Strategy code executes unchanged - Portfolio and recording operate identically to live mode -See `docs/backtesting_guide.md` for detailed usage. +See `docs/backtesting_guide.md` for the current cache-backed workflow. ## Live Trading (IG) @@ -116,7 +116,19 @@ Users can subscribe to recording events for custom reporting pipelines. ## Installation -Install using your preferred environment manager. Ensure Python 3.11+. +Python 3.11+ is required. + +Install the published package: + +```bash +pip install tradedesk +``` + +For local development: + +```bash +pip install -e '.[dev]' +``` ## Documentation @@ -131,6 +143,15 @@ See the `docs/` directory for: - Risk management guide - Metrics guide +Public package entry points are grouped under: + +- `tradedesk.marketdata` +- `tradedesk.execution` +- `tradedesk.execution.backtest` +- `tradedesk.portfolio` +- `tradedesk.recording` +- `tradedesk.strategy` + tradedesk is designed for clarity, determinism, and event-level transparency. @@ -142,4 +163,3 @@ Licensed under the Apache License, Version 2.0. See: [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) Copyright 2026 [Radius Red Ltd.](https://github.com/radiusred) - diff --git a/docs/aggregation_guide.md b/docs/aggregation_guide.md index f169631..44a3270 100644 --- a/docs/aggregation_guide.md +++ b/docs/aggregation_guide.md @@ -1,6 +1,6 @@ # Candle Aggregation Guide -The `tradedesk.aggregation` module provides time-bucketing candle aggregation for converting base-period candles into higher timeframes. +The `tradedesk.marketdata` module provides time-bucketing candle aggregation for converting base-period candles into higher timeframes. ## Overview @@ -14,7 +14,7 @@ The `tradedesk.aggregation` module provides time-bucketing candle aggregation fo ## Basic Usage ```python -from tradedesk.aggregation import CandleAggregator +from tradedesk.marketdata import CandleAggregator from tradedesk import Candle # Create aggregator for 15-minute candles from 5-minute base period @@ -49,7 +49,7 @@ assert result.close == 1.125 # Last close Use `choose_base_period()` to automatically select an appropriate base period for your broker: ```python -from tradedesk.aggregation import choose_base_period +from tradedesk.marketdata import choose_base_period # Default: Uses common broker periods (SECOND, 1MINUTE, 5MINUTE, HOUR) base = choose_base_period("15MINUTE") # Returns "1MINUTE" @@ -157,7 +157,7 @@ The aggregator is gap-tolerant: ## Complete Example: Live Aggregation ```python -from tradedesk.aggregation import CandleAggregator +from tradedesk.marketdata import CandleAggregator class LiveAggregationStrategy: def __init__(self, target_period: str): diff --git a/docs/backtesting_guide.md b/docs/backtesting_guide.md index 52981b2..edb14a3 100644 --- a/docs/backtesting_guide.md +++ b/docs/backtesting_guide.md @@ -1,12 +1,12 @@ # Backtesting Guide This guide covers running backtests with tradedesk using candle data loaded from -CSV files or supplied in-memory. +the Dukascopy cache or supplied in-memory. By the end you will have: - A working strategy -- A CSV-driven backtest via `run_portfolio` +- A cache-backed backtest via `run_portfolio` - A full recorded backtest via `run_backtest` (with metrics and trade output) The same strategy runs live against a broker without modification. @@ -19,21 +19,30 @@ The same strategy runs live against a broker without modification. my_backtest/ strategy.py run_backtest.py - candles.csv ``` --- -## 2. Candle CSV Format +## 2. Dukascopy Cache Input -``` -timestamp,open,high,low,close,volume -2025-01-01T00:00:00Z,1.2500,1.2510,1.2490,1.2505,1000 -2025-01-01T00:05:00Z,1.2505,1.2520,1.2500,1.2515,800 -``` +`BacktestClient.from_dukascopy_cache(...)` reads 1-minute candle files from a +Dukascopy cache directory and aggregates them to the period your strategy +subscribes to. + +Required inputs: + +- `cache_dir`: root cache directory +- `symbol`: cache symbol folder, for example `GBPUSD` +- `instrument`: instrument identifier used by your strategy +- `period`: target tradedesk period such as `5MINUTE` or `HOUR` +- `date_from` / `date_to`: inclusive date range +- `price_side`: `"bid"` or `"ask"` (`"bid"` is the default) + +Example shared cache location used at Radius Red: -Fields `volume` and `tick_count` are optional. -Timestamps may use `-` or `/` as date separators, with or without a trailing `Z`. +```text +/paperclip/tradedesk/marketdata/GBPUSD/2026/00/01_bid.csv.zst +``` --- @@ -82,6 +91,8 @@ code path as live trading. ```python # run_backtest.py +from datetime import date + from tradedesk import SimplePortfolio, run_portfolio from tradedesk.execution.backtest.client import BacktestClient @@ -89,10 +100,14 @@ from strategy import SimpleMomentumStrategy def client_factory(): - return BacktestClient.from_csv( - "candles.csv", + return BacktestClient.from_dukascopy_cache( + "/paperclip/tradedesk/marketdata", + symbol="GBPUSD", instrument="CS.D.GBPUSD.TODAY.IP", period="5MINUTE", + date_from=date(2025, 1, 1), + date_to=date(2025, 1, 31), + price_side="bid", ) @@ -112,7 +127,14 @@ To capture the client for inspection, use a closure: created = {} def client_factory(): - c = BacktestClient.from_csv("candles.csv", instrument="CS.D.GBPUSD.TODAY.IP", period="5MINUTE") + c = BacktestClient.from_dukascopy_cache( + "/paperclip/tradedesk/marketdata", + symbol="GBPUSD", + instrument="CS.D.GBPUSD.TODAY.IP", + period="5MINUTE", + date_from=date(2025, 1, 1), + date_to=date(2025, 1, 31), + ) created["client"] = c return c @@ -169,6 +191,7 @@ run_portfolio( ```python import asyncio +from datetime import date from pathlib import Path from tradedesk import SimplePortfolio @@ -181,7 +204,11 @@ async def main(): spec = BacktestSpec( instrument="CS.D.GBPUSD.TODAY.IP", period="5MINUTE", - candle_csv=Path("candles.csv"), + cache_dir=Path("/paperclip/tradedesk/marketdata"), + symbol="GBPUSD", + date_from=date(2025, 1, 1), + date_to=date(2025, 1, 31), + price_side="bid", half_spread_adjustment=0.5, # add half the spread to BID-sourced candles ) diff --git a/docs/metrics_guide.md b/docs/metrics_guide.md index 44eb058..9d7e808 100644 --- a/docs/metrics_guide.md +++ b/docs/metrics_guide.md @@ -1,6 +1,6 @@ # Performance Metrics Guide -The `tradedesk.metrics` module provides tools for analyzing trading strategy performance. +The `tradedesk.recording` module provides tools for analyzing trading strategy performance. ## Overview @@ -13,7 +13,7 @@ The metrics module helps you: ## Quick Start ```python -from tradedesk.metrics import compute_metrics +from tradedesk.recording import compute_metrics # Your trade fills trade_rows = [ @@ -44,7 +44,7 @@ print(f"Max Drawdown: {metrics.max_drawdown:.2f}") Convert fill history into complete round-trip trades: ```python -from tradedesk.metrics import round_trips_from_fills +from tradedesk.recording import round_trips_from_fills fills = [ {"instrument": "EURUSD", "direction": "BUY", "timestamp": "2025-01-01T10:00:00Z", "price": "1.1000", "size": "2"}, @@ -86,7 +86,7 @@ trips = round_trips_from_fills(fills) The `Metrics` dataclass contains comprehensive performance statistics: ```python -from tradedesk.metrics import Metrics, compute_metrics +from tradedesk.recording import Metrics, compute_metrics metrics = compute_metrics(equity_rows, trade_rows) @@ -157,7 +157,7 @@ assert metrics.final_equity == 0.0 Build an equity curve from round-trip P&L: ```python -from tradedesk.metrics import round_trips_from_fills, equity_rows_from_round_trips +from tradedesk.recording import round_trips_from_fills, equity_rows_from_round_trips fills = [ {"instrument": "EURUSD", "direction": "BUY", "timestamp": "2025-01-01T00:00:00Z", "price": "100", "size": "1"}, @@ -216,7 +216,7 @@ print(f"Avg win: ${metrics_usd.avg_win}") Calculate maximum drawdown from an equity curve: ```python -from tradedesk.metrics import max_drawdown +from tradedesk.recording.metrics import max_drawdown equity = [100, 110, 105, 95, 120, 115] dd = max_drawdown(equity) # -15.0 (peak 110, trough 95) @@ -229,7 +229,7 @@ assert max_drawdown([100, 101, 102]) == 0.0 # Monotonic up ## Complete Example: Strategy Analysis ```python -from tradedesk.metrics import compute_metrics, round_trips_from_fills +from tradedesk.recording import compute_metrics, round_trips_from_fills class StrategyAnalyzer: def __init__(self): diff --git a/docs/risk_management.md b/docs/risk_management.md index 4ad7ced..b35844e 100644 --- a/docs/risk_management.md +++ b/docs/risk_management.md @@ -1,6 +1,6 @@ # Risk Management Guide -The `tradedesk.risk` and `tradedesk.position` modules provide utilities for position sizing and position state tracking. +The `tradedesk.portfolio` and `tradedesk.execution` modules provide utilities for position sizing and position state tracking. ## Position Sizing @@ -9,7 +9,7 @@ The `tradedesk.risk` and `tradedesk.position` modules provide utilities for posi The `atr_normalised_size()` function calculates position size based on Average True Range (ATR): ```python -from tradedesk.risk import atr_normalised_size +from tradedesk.portfolio import atr_normalised_size # Calculate position size size = atr_normalised_size( @@ -61,7 +61,7 @@ size = atr_normalised_size( ```python # Adjust position size based on market volatility -from tradedesk.indicators import ATR +from tradedesk.marketdata.indicators import ATR atr_indicator = ATR(period=14) @@ -86,7 +86,7 @@ if current_atr: The `PositionTracker` class maintains state for an open position: ```python -from tradedesk.position import PositionTracker +from tradedesk.execution import PositionTracker from tradedesk.types import Direction # Create tracker @@ -155,7 +155,7 @@ assert position.mfe_points == 7.0 # 107 - 100 (updated to new max) ### Complete Position Lifecycle ```python -from tradedesk.position import PositionTracker +from tradedesk.execution import PositionTracker from tradedesk.types import Direction class MyStrategy: diff --git a/docs/strategy_guide.md b/docs/strategy_guide.md index 80f1e2e..07da5e7 100644 --- a/docs/strategy_guide.md +++ b/docs/strategy_guide.md @@ -296,8 +296,7 @@ The implementation uses two cooperating components: ```python from dataclasses import dataclass -from tradedesk.indicators.ema import EMA -from tradedesk.indicators.atr import ATR +from tradedesk.marketdata.indicators import ATR, EMA @dataclass