Storage¶
mt5cli.storage ¶
Generic storage helpers for MT5 market and account history.
__all__
module-attribute
¶
__all__ = [
"Dataset",
"IfExists",
"OutputFormat",
"RateTarget",
"build_rate_targets",
"build_rate_view_name",
"collect_history",
"detect_format",
"drop_forming_rate_bar",
"export_dataframe",
"export_dataframe_to_sqlite",
"load_rate_data",
"load_rate_data_from_connection",
"load_rate_series_by_granularity",
"load_rate_series_from_sqlite",
"resolve_rate_tables",
"resolve_rate_view_name",
"resolve_rate_view_names",
"update_history",
"update_history_with_config",
]
Dataset ¶
Bases: StrEnum
Datasets supported by the collect-history command.
IfExists ¶
OutputFormat ¶
RateTarget
dataclass
¶
A single rate series identified by symbol and timeframe.
Attributes:
| Name | Type | Description |
|---|---|---|
symbol |
str | None
|
MT5 symbol name, or None when the rate series is addressed only by an explicit table (for example a custom SQLite view). |
timeframe |
int | str
|
MT5 timeframe as an integer or name (for example |
__post_init__ ¶
Normalize accepted timeframe aliases to the stored integer value.
build_rate_targets ¶
build_rate_targets(
symbols: Sequence[str],
timeframes: Sequence[int | str],
*,
allow_missing_symbol: bool = False,
) -> list[RateTarget]
Build rate targets for every symbol and timeframe combination.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
symbols
|
Sequence[str]
|
MT5 symbol names. May be empty when |
required |
timeframes
|
Sequence[int | str]
|
MT5 timeframes as integers or names (for example |
required |
allow_missing_symbol
|
bool
|
When True and |
False
|
Returns:
| Type | Description |
|---|---|
list[RateTarget]
|
Targets in row-major order: every timeframe for the first symbol, then |
list[RateTarget]
|
every timeframe for the next symbol, and so on. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in mt5cli/history.py
build_rate_view_name ¶
build_rate_view_name(
*,
symbol: str,
granularity: str,
granularity_count: int,
timeframe: int,
) -> str
Return a collision-free offline optimize view name.
View names always include the timeframe integer after a __ separator so
a symbol such as EURUSD_M1 cannot collide with EURUSD at timeframe
M1.
Source code in mt5cli/history.py
collect_history ¶
collect_history(
output: Path,
symbols: list[str],
date_from: datetime | str,
date_to: datetime | str,
*,
datasets: set[Dataset] | None = None,
timeframe: int | str = 1,
flags: int | str = "ALL",
if_exists: IfExists = FAIL,
with_views: bool = False,
config: Mt5Config | None = None,
) -> None
Collect historical datasets into a single SQLite database.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output
|
Path
|
SQLite database path. |
required |
symbols
|
list[str]
|
Symbols to collect. |
required |
date_from
|
datetime | str
|
Start date. |
required |
date_to
|
datetime | str
|
End date. |
required |
datasets
|
set[Dataset] | None
|
Datasets to include (defaults to all). |
None
|
timeframe
|
int | str
|
Rates timeframe as integer or name (e.g. |
1
|
flags
|
int | str
|
Tick copy flags as integer or name (e.g. |
'ALL'
|
if_exists
|
IfExists
|
Behavior when a target table already exists. |
FAIL
|
with_views
|
bool
|
Create |
False
|
config
|
Mt5Config | None
|
MT5 connection configuration. |
None
|
Source code in mt5cli/sdk.py
1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 | |
detect_format ¶
Detect the output format from a file extension or explicit format string.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output_path
|
Path
|
Path to the output file. |
required |
explicit_format
|
str | None
|
Explicitly specified format, if any. |
None
|
Returns:
| Type | Description |
|---|---|
str
|
The detected format string. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the format cannot be determined. |
Source code in mt5cli/utils.py
drop_forming_rate_bar ¶
Return closed bars from chronologically ordered MT5 rate data.
MetaTrader 5 copy_rates_from_pos(start_pos=0) includes the still-forming
current bar as the last row. Slice it off so downstream logic only sees
completed bars. Empty frames and single-row frames return empty results.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df_rate
|
DataFrame
|
Rate data ordered oldest-to-newest with the forming bar last. |
required |
Returns:
| Type | Description |
|---|---|
DataFrame
|
A new DataFrame with all rows except the last. Index and columns are |
DataFrame
|
preserved. The input frame is not modified. |
Source code in mt5cli/history.py
export_dataframe ¶
export_dataframe(
df: DataFrame,
output_path: Path,
output_format: str,
table_name: str = "data",
) -> None
Export a pandas DataFrame to the specified file format.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
DataFrame to export. |
required |
output_path
|
Path
|
Path to the output file. |
required |
output_format
|
str
|
Output format (csv, json, parquet, or sqlite3). |
required |
table_name
|
str
|
Table name for SQLite3 output. |
'data'
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If the output format is not supported. |
Source code in mt5cli/utils.py
export_dataframe_to_sqlite ¶
export_dataframe_to_sqlite(
df: DataFrame,
output_path: Path,
table_name: str = "data",
*,
if_exists: IfExists = APPEND,
index: bool = False,
index_label: str | None = None,
deduplicate_on: Sequence[str] | None = None,
) -> None
Write a DataFrame to SQLite with configurable append and deduplication.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
DataFrame to export. |
required |
output_path
|
Path
|
SQLite database path. |
required |
table_name
|
str
|
Target table name. |
'data'
|
if_exists
|
IfExists
|
Conflict behavior when the table already exists. |
APPEND
|
index
|
bool
|
Whether to write the DataFrame index as a column. |
False
|
index_label
|
str | None
|
Column name for the index when |
None
|
deduplicate_on
|
Sequence[str] | None
|
Optional key columns to deduplicate after writing,
keeping the latest |
None
|
Source code in mt5cli/utils.py
load_rate_data ¶
load_rate_data(
conn_or_path: SqliteConnOrPath,
table: str,
count: int | None = None,
) -> DataFrame
Load rate-like data from a SQLite database path or connection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
conn_or_path
|
SqliteConnOrPath
|
SQLite database path or open connection. |
required |
table
|
str
|
Source table or view name. |
required |
count
|
int | None
|
Optional number of most recent rows to load. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame indexed by ascending |
Source code in mt5cli/history.py
load_rate_data_from_connection ¶
load_rate_data_from_connection(
connection: Connection,
table: str,
count: int | None = None,
) -> DataFrame
Load rate-like data from a SQLite table or view.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
connection
|
Connection
|
Open SQLite connection. |
required |
table
|
str
|
Source table or view name. |
required |
count
|
int | None
|
Optional number of most recent rows to load. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame indexed by ascending |
Raises:
| Type | Description |
|---|---|
ValueError
|
If inputs, schema, timestamps are invalid, or the table or view contains no rows. |
Source code in mt5cli/history.py
load_rate_series_by_granularity ¶
load_rate_series_by_granularity(
conn_or_path: SqliteConnOrPath,
symbols: Sequence[str],
granularities: Sequence[int | str],
count: int,
*,
explicit_tables: Sequence[str] | None = None,
allow_missing_symbol: bool = False,
) -> dict[tuple[str | None, str], DataFrame]
Load rate series keyed by symbol and string granularity name.
Builds targets with :func:build_rate_targets and loads them with
:func:load_rate_series_from_sqlite, then rekeys the result by granularity
name (for example M1) instead of the integer timeframe to reduce
downstream boilerplate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
conn_or_path
|
SqliteConnOrPath
|
SQLite database path or open connection. |
required |
symbols
|
Sequence[str]
|
MT5 symbol names. May be empty when |
required |
granularities
|
Sequence[int | str]
|
MT5 timeframes as integers or names (for example |
required |
count
|
int
|
Number of most recent rows to load per series. |
required |
explicit_tables
|
Sequence[str] | None
|
Optional explicit table or view names matching the built targets in row-major order. Required when symbols are omitted. |
None
|
allow_missing_symbol
|
bool
|
When True and |
False
|
Returns:
| Type | Description |
|---|---|
dict[tuple[str | None, str], DataFrame]
|
Mapping keyed by |
dict[tuple[str | None, str], DataFrame]
|
DataFrame. Propagates |
dict[tuple[str | None, str], DataFrame]
|
func: |
dict[tuple[str | None, str], DataFrame]
|
table resolution fails, or duplicate targets are present. |
Source code in mt5cli/history.py
load_rate_series_from_sqlite ¶
load_rate_series_from_sqlite(
conn_or_path: SqliteConnOrPath,
targets: Sequence[RateTarget],
count: int,
explicit_tables: Sequence[str] | None = None,
) -> dict[tuple[str | None, int], DataFrame]
Load multiple rate series from a SQLite database.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
conn_or_path
|
SqliteConnOrPath
|
SQLite database path or open connection. |
required |
targets
|
Sequence[RateTarget]
|
Rate targets to load. Each |
required |
count
|
int
|
Number of most recent rows to load per series. |
required |
explicit_tables
|
Sequence[str] | None
|
Optional explicit table or view names matching targets.
When omitted, managed |
None
|
Returns:
| Type | Description |
|---|---|
dict[tuple[str | None, int], DataFrame]
|
Mapping keyed by |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in mt5cli/history.py
resolve_rate_tables ¶
resolve_rate_tables(
conn_or_path: SqliteConnOrPath | None,
targets: Sequence[RateTarget],
explicit_tables: Sequence[str] | None = None,
*,
require_existing: bool = False,
) -> list[str]
Resolve SQLite table or view names for rate targets.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
conn_or_path
|
SqliteConnOrPath | None
|
SQLite database path or open connection. May be None when
|
required |
targets
|
Sequence[RateTarget]
|
Rate targets to resolve. |
required |
explicit_tables
|
Sequence[str] | None
|
Optional explicit table or view names. When provided, they are used as-is and must match the number of targets. |
None
|
require_existing
|
bool
|
When True, require the database and managed views to
exist for each symbol target. Ignored when |
False
|
Returns:
| Type | Description |
|---|---|
list[str]
|
Table or view names aligned with |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in mt5cli/history.py
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 | |
resolve_rate_view_name ¶
resolve_rate_view_name(
conn_or_path: SqliteConnOrPath | None,
symbol: str,
granularity: str,
*,
require_existing: bool = False,
) -> str
Resolve the mt5cli-managed rate compatibility view name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
conn_or_path
|
SqliteConnOrPath | None
|
SQLite database path or open connection. When None or a
non-existing path and |
required |
symbol
|
str
|
Symbol stored in the normalized |
required |
granularity
|
str
|
Timeframe name (for example |
required |
require_existing
|
bool
|
When True, require the database and a managed view to exist. |
False
|
Returns:
| Type | Description |
|---|---|
str
|
View name such as |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in mt5cli/history.py
resolve_rate_view_names ¶
resolve_rate_view_names(
conn_or_path: SqliteConnOrPath | None,
symbols: Sequence[str],
granularities: Sequence[str],
*,
require_existing: bool = False,
) -> list[str]
Resolve rate compatibility view names for symbol and granularity pairs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
conn_or_path
|
SqliteConnOrPath | None
|
SQLite database path or open connection. When None or a
non-existing path and |
required |
symbols
|
Sequence[str]
|
Symbols stored in the normalized |
required |
granularities
|
Sequence[str]
|
Timeframe names (for example |
required |
require_existing
|
bool
|
When True, require the database and managed views to exist. |
False
|
Returns:
| Type | Description |
|---|---|
list[str]
|
View names in row-major order: every |
list[str]
|
symbol, then every granularity for the next symbol, and so on. |
Source code in mt5cli/history.py
update_history ¶
update_history(
*,
client: Mt5DataClient,
output: Path | str,
symbols: Sequence[str],
datasets: set[Dataset] | None = None,
timeframes: Sequence[int | str] | None = None,
flags: int | str = "ALL",
lookback_hours: float = 24.0,
date_to: datetime | str | None = None,
deduplicate: bool = True,
create_rate_views: bool = True,
with_views: bool = False,
include_account_events: bool = True,
) -> None
Incrementally append MT5 history into a SQLite database.
Uses an already-connected Mt5DataClient and does not create or close
the MT5 connection. For first-time tables, data is fetched from
date_to - lookback_hours. Subsequent runs resume from existing
MAX(time) per symbol (and timeframe for rates); when
include_account_events=True, account-level deals use a separate cursor
over type NOT IN (0, 1) / empty-symbol rows.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client
|
Mt5DataClient
|
Connected MT5 data client. |
required |
output
|
Path | str
|
SQLite database path. |
required |
symbols
|
Sequence[str]
|
Symbols to update. |
required |
datasets
|
set[Dataset] | None
|
Datasets to include (defaults to all). |
None
|
timeframes
|
Sequence[int | str] | None
|
Rate timeframes to update (defaults to all fixed MT5 timeframes when None). |
None
|
flags
|
int | str
|
Tick copy flags as integer or name (e.g. |
'ALL'
|
lookback_hours
|
float
|
First-run lookback when a table has no prior rows. |
24.0
|
date_to
|
datetime | str | None
|
Optional update end datetime. Defaults to now (UTC). |
None
|
deduplicate
|
bool
|
Remove duplicate rows after append, keeping latest ROWID. |
True
|
create_rate_views
|
bool
|
Create |
True
|
with_views
|
bool
|
Create |
False
|
include_account_events
|
bool
|
Include account-level cash events in
|
True
|
Source code in mt5cli/sdk.py
update_history_with_config ¶
update_history_with_config(
*,
output: Path | str,
symbols: Sequence[str],
config: Mt5Config | None = None,
datasets: set[Dataset] | None = None,
timeframes: Sequence[int | str] | None = None,
flags: int | str = "ALL",
lookback_hours: float = 24.0,
date_to: datetime | str | None = None,
deduplicate: bool = True,
create_rate_views: bool = True,
with_views: bool = False,
include_account_events: bool = True,
) -> None
Incrementally append MT5 history, opening and closing the MT5 connection.
Convenience wrapper around :func:update_history for standalone use.