# theorycraft-trading/dukascopy architecture

> Architecture diagram of the GitHub repository theorycraft-trading/dukascopy, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-28). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/theorycraft-trading/dukascopy
- Repository: https://github.com/theorycraft-trading/dukascopy

## Overview

Dukascopy is an Elixir client and CLI for downloading and streaming historical tick and bar data from Dukascopy. The primary workflow validates an instrument, timeframe, and date range; selects and fetches the appropriate historical files; then exposes tick/bar events, optionally resampled for the requested timeframe. The README also documents instrument search and CLI serialization to CSV, JSON, NDJSON, or no file. The graph includes those documented capabilities, but several runtime modules were not sampled, so uncertain internal calls are omitted.

Main entry points: [`lib/dukascopy.ex`](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy.ex) (Stream API), [`lib/dukascopy/cli.ex`](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/cli.ex) (CLI commands), [`lib/dukascopy/paginator.ex`](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/paginator.ex) (Page retrieval), [`lib/dukascopy/instruments.ex`](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/instruments.ex) (Instrument catalog)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_api["Streaming API"]
  node_dukascopy_api["Stream API<br/>[dukascopy.ex]"]
  node_options["Option validation<br/>[options.ex]"]
  node_data_feed["TheoryCraft feed<br/>[data_feed.ex]"]
end

subgraph group_fetch["Historical Fetch"]
  node_bar_data["Bar data<br/>[bar_data.ex]"]
  node_tick_data["Tick data<br/>[tick_data.ex]"]
  node_paginator["Page retrieval<br/>[paginator.ex]"]
  node_page["Page results<br/>[page.ex]"]
  node_cursor["Page cursor<br/>[cursor.ex]"]
  node_periods["Fetch periods"]
  node_time_range["Range fallback<br/>[time_range.ex]"]
  node_urls["URL generation<br/>[url_generator.ex]"]
  node_client["HTTP client<br/>[client.ex]"]
end

subgraph group_instruments["Instrument Catalog"]
  node_instruments_api["Instrument catalog<br/>[instruments.ex]"]
  node_instrument_data["Instrument metadata<br/>[instruments.json]"]
end

subgraph group_cli["Command Line"]
  node_cli["CLI commands<br/>[cli.ex]"]
  node_cli_options["CLI options<br/>[options.ex]"]
  node_formatter["Output formatter<br/>[formatter.ex]"]
  node_printer["CLI output<br/>[printer.ex]"]
end

node_caller(("API consumer"))
node_dukascopy_service(("Dukascopy datafeed"))
node_cache[("File cache")]
node_download_files["Downloaded files"]

node_caller -->|"requests stream"| node_dukascopy_api
node_dukascopy_api -->|"validates options"| node_options
node_dukascopy_api -->|"fetches page"| node_paginator
node_dukascopy_api -->|"builds feed"| node_data_feed
node_dukascopy_api -->|"returns events"| node_caller
node_paginator -->|"uses cursor"| node_cursor
node_paginator -->|"returns page"| node_page
node_urls -->|"looks up filename"| node_instruments_api
node_instruments_api -->|"loads metadata"| node_instrument_data
node_client -->|"requests files"| node_dukascopy_service
node_client -.->|"reads/writes"| node_cache
node_cli -->|"parses arguments"| node_cli_options
node_cli -->|"requests stream"| node_dukascopy_api
node_cli -->|"searches catalog"| node_instruments_api
node_cli -->|"formats events"| node_formatter
node_cli -->|"prints status"| node_printer
node_formatter -->|"serializes output"| node_download_files

click node_dukascopy_api "https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy.ex"
click node_options "https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/options.ex"
click node_data_feed "https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/data_feed.ex"
click node_bar_data "https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/bar_data.ex"
click node_tick_data "https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/tick_data.ex"
click node_paginator "https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/paginator.ex"
click node_page "https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/page.ex"
click node_cursor "https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/cursor.ex"
click node_periods "https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/helpers/period_generator.ex"
click node_time_range "https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/helpers/time_range.ex"
click node_urls "https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/helpers/url_generator.ex"
click node_client "https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/client.ex"
click node_instruments_api "https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/instruments.ex"
click node_instrument_data "https://github.com/theorycraft-trading/dukascopy/blob/main/priv/instruments.json"
click node_cli "https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/cli.ex"
click node_cli_options "https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/cli/options.ex"
click node_formatter "https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/cli/formatter.ex"
click node_printer "https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/cli/printer.ex"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_dukascopy_api,node_options,node_data_feed toneBlue
class node_bar_data,node_tick_data,node_paginator,node_page,node_cursor,node_periods,node_time_range,node_urls,node_client,node_cache toneAmber
class node_instruments_api,node_instrument_data,node_caller toneMint
class node_cli,node_cli_options,node_formatter,node_printer toneRose
class node_dukascopy_service,node_download_files toneIndigo
```

## Components

### Streaming API

- [Stream API](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy.ex): `lib/dukascopy.ex`
- [Option validation](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/options.ex): `lib/dukascopy/options.ex`
- [TheoryCraft feed](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/data_feed.ex): `lib/dukascopy/data_feed.ex`

### Historical Fetch

- [Bar data](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/bar_data.ex): `lib/dukascopy/bar_data.ex`
- [Tick data](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/tick_data.ex): `lib/dukascopy/tick_data.ex`
- [Page retrieval](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/paginator.ex): `lib/dukascopy/paginator.ex`
- [Page results](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/page.ex): `lib/dukascopy/page.ex`
- [Page cursor](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/cursor.ex): `lib/dukascopy/cursor.ex`
- [Fetch periods](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/helpers/period_generator.ex): `lib/dukascopy/helpers/period_generator.ex`
- [Range fallback](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/helpers/time_range.ex): `lib/dukascopy/helpers/time_range.ex`
- [URL generation](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/helpers/url_generator.ex): `lib/dukascopy/helpers/url_generator.ex`
- [HTTP client](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/client.ex): `lib/dukascopy/client.ex`

### Instrument Catalog

- [Instrument catalog](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/instruments.ex): `lib/dukascopy/instruments.ex`
- [Instrument metadata](https://github.com/theorycraft-trading/dukascopy/blob/main/priv/instruments.json): `priv/instruments.json`

### Command Line

- [CLI commands](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/cli.ex): `lib/dukascopy/cli.ex`
- [CLI options](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/cli/options.ex): `lib/dukascopy/cli/options.ex`
- [Output formatter](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/cli/formatter.ex): `lib/dukascopy/cli/formatter.ex`
- [CLI output](https://github.com/theorycraft-trading/dukascopy/blob/main/lib/dukascopy/cli/printer.ex): `lib/dukascopy/cli/printer.ex`

### Other components

- **API consumer**
- **Dukascopy datafeed**
- **File cache**
- **Downloaded files**

## Connections

- API consumer → Stream API: requests stream
- Stream API → Option validation: validates options
- Stream API → Page retrieval: fetches page
- Stream API → TheoryCraft feed: builds feed
- Stream API → API consumer: returns events
- Page retrieval → Page cursor: uses cursor
- Page retrieval → Page results: returns page
- URL generation → Instrument catalog: looks up filename
- Instrument catalog → Instrument metadata: loads metadata
- HTTP client → Dukascopy datafeed: requests files
- HTTP client → File cache: reads/writes
- CLI commands → CLI options: parses arguments
- CLI commands → Stream API: requests stream
- CLI commands → Instrument catalog: searches catalog
- CLI commands → Output formatter: formats events
- CLI commands → CLI output: prints status
- Output formatter → Downloaded files: serializes output
