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
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 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 | |
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: None = None,
count: int | None = None,
explicit_tables: None = None,
*,
table: str,
) -> DataFrame
load_rate_series_from_sqlite(
conn_or_path: SqliteConnOrPath,
targets: None = None,
count: int | None = None,
explicit_tables: Sequence[str] | None = None,
*,
table: None = None,
) -> dict[tuple[str | None, int], DataFrame]
load_rate_series_from_sqlite(
conn_or_path: SqliteConnOrPath,
targets: Sequence[RateTarget],
count: int,
explicit_tables: Sequence[str] | None = None,
*,
table: None = None,
) -> dict[tuple[str | None, int], DataFrame]
load_rate_series_from_sqlite(
conn_or_path: SqliteConnOrPath,
targets: Sequence[RateTarget] | None = None,
count: int | None = None,
explicit_tables: Sequence[str] | None = None,
*,
table: str | None = None,
) -> dict[tuple[str | None, int], DataFrame] | DataFrame
Load one table/view or 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] | None
|
Rate targets to load. Each |
None
|
count
|
int | None
|
Optional number of most recent rows to load per series. |
None
|
explicit_tables
|
Sequence[str] | None
|
Optional explicit table or view names matching targets.
When omitted, managed |
None
|
table
|
str | None
|
Optional single table or view name to load directly. |
None
|
Returns:
| Type | Description |
|---|---|
dict[tuple[str | None, int], DataFrame] | DataFrame
|
A DataFrame when |
dict[tuple[str | None, int], DataFrame] | DataFrame
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in mt5cli/history.py
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 | |
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
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 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 | |
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.