mt5api 0.0.4__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. {mt5api-0.0.4 → mt5api-0.2.0}/.agents/skills/local-qa/SKILL.md +1 -1
  2. {mt5api-0.0.4 → mt5api-0.2.0}/.agents/skills/local-qa/scripts/qa.sh +1 -1
  3. {mt5api-0.0.4 → mt5api-0.2.0}/.agents/skills/mt5api/SKILL.md +73 -2
  4. {mt5api-0.0.4 → mt5api-0.2.0}/.github/workflows/ci.yml +1 -22
  5. mt5api-0.2.0/.github/workflows/release.yml +44 -0
  6. {mt5api-0.0.4 → mt5api-0.2.0}/AGENTS.md +4 -2
  7. {mt5api-0.0.4 → mt5api-0.2.0}/PKG-INFO +33 -8
  8. {mt5api-0.0.4 → mt5api-0.2.0}/README.md +32 -6
  9. {mt5api-0.0.4 → mt5api-0.2.0}/docs/api/deployment.md +0 -2
  10. {mt5api-0.0.4 → mt5api-0.2.0}/docs/api/rest-api.md +21 -11
  11. {mt5api-0.0.4 → mt5api-0.2.0}/docs/index.md +3 -3
  12. {mt5api-0.0.4 → mt5api-0.2.0}/mt5api/config.py +0 -22
  13. {mt5api-0.0.4 → mt5api-0.2.0}/mt5api/constants.py +0 -4
  14. mt5api-0.2.0/mt5api/dependencies.py +236 -0
  15. {mt5api-0.0.4 → mt5api-0.2.0}/mt5api/main.py +13 -55
  16. {mt5api-0.0.4 → mt5api-0.2.0}/mt5api/middleware.py +1 -54
  17. {mt5api-0.0.4 → mt5api-0.2.0}/mt5api/models.py +56 -0
  18. mt5api-0.2.0/mt5api/routers/__init__.py +16 -0
  19. mt5api-0.2.0/mt5api/routers/connection.py +72 -0
  20. {mt5api-0.0.4 → mt5api-0.2.0}/mt5api/routers/market.py +2 -2
  21. {mt5api-0.0.4 → mt5api-0.2.0}/mt5api/routers/trading.py +4 -4
  22. {mt5api-0.0.4 → mt5api-0.2.0}/pyproject.toml +1 -2
  23. {mt5api-0.0.4 → mt5api-0.2.0}/tests/test_config.py +0 -28
  24. mt5api-0.2.0/tests/test_connection.py +467 -0
  25. {mt5api-0.0.4 → mt5api-0.2.0}/tests/test_main.py +22 -27
  26. {mt5api-0.0.4 → mt5api-0.2.0}/tests/test_middleware.py +0 -24
  27. {mt5api-0.0.4 → mt5api-0.2.0}/uv.lock +62 -159
  28. mt5api-0.0.4/mt5api/dependencies.py +0 -132
  29. mt5api-0.0.4/mt5api/routers/__init__.py +0 -7
  30. {mt5api-0.0.4 → mt5api-0.2.0}/.agents/skills/speckit-analyze/SKILL.md +0 -0
  31. {mt5api-0.0.4 → mt5api-0.2.0}/.agents/skills/speckit-checklist/SKILL.md +0 -0
  32. {mt5api-0.0.4 → mt5api-0.2.0}/.agents/skills/speckit-clarify/SKILL.md +0 -0
  33. {mt5api-0.0.4 → mt5api-0.2.0}/.agents/skills/speckit-constitution/SKILL.md +0 -0
  34. {mt5api-0.0.4 → mt5api-0.2.0}/.agents/skills/speckit-implement/SKILL.md +0 -0
  35. {mt5api-0.0.4 → mt5api-0.2.0}/.agents/skills/speckit-plan/SKILL.md +0 -0
  36. {mt5api-0.0.4 → mt5api-0.2.0}/.agents/skills/speckit-specify/SKILL.md +0 -0
  37. {mt5api-0.0.4 → mt5api-0.2.0}/.agents/skills/speckit-tasks/SKILL.md +0 -0
  38. {mt5api-0.0.4 → mt5api-0.2.0}/.agents/skills/speckit-taskstoissues/SKILL.md +0 -0
  39. {mt5api-0.0.4 → mt5api-0.2.0}/.claude/agents/codex.md +0 -0
  40. {mt5api-0.0.4 → mt5api-0.2.0}/.claude/agents/copilot.md +0 -0
  41. {mt5api-0.0.4 → mt5api-0.2.0}/.claude/commands/speckit.analyze.md +0 -0
  42. {mt5api-0.0.4 → mt5api-0.2.0}/.claude/commands/speckit.checklist.md +0 -0
  43. {mt5api-0.0.4 → mt5api-0.2.0}/.claude/commands/speckit.clarify.md +0 -0
  44. {mt5api-0.0.4 → mt5api-0.2.0}/.claude/commands/speckit.constitution.md +0 -0
  45. {mt5api-0.0.4 → mt5api-0.2.0}/.claude/commands/speckit.implement.md +0 -0
  46. {mt5api-0.0.4 → mt5api-0.2.0}/.claude/commands/speckit.plan.md +0 -0
  47. {mt5api-0.0.4 → mt5api-0.2.0}/.claude/commands/speckit.specify.md +0 -0
  48. {mt5api-0.0.4 → mt5api-0.2.0}/.claude/commands/speckit.tasks.md +0 -0
  49. {mt5api-0.0.4 → mt5api-0.2.0}/.claude/commands/speckit.taskstoissues.md +0 -0
  50. {mt5api-0.0.4 → mt5api-0.2.0}/.claude/settings.json +0 -0
  51. {mt5api-0.0.4 → mt5api-0.2.0}/.github/FUNDING.yml +0 -0
  52. {mt5api-0.0.4 → mt5api-0.2.0}/.github/dependabot.yml +0 -0
  53. {mt5api-0.0.4 → mt5api-0.2.0}/.github/renovate.json +0 -0
  54. /mt5api-0.0.4/.github/workflows/claude-code.yml → /mt5api-0.2.0/.github/workflows/claude.yml +0 -0
  55. {mt5api-0.0.4 → mt5api-0.2.0}/.gitignore +0 -0
  56. {mt5api-0.0.4 → mt5api-0.2.0}/.specify/memory/constitution.md +0 -0
  57. {mt5api-0.0.4 → mt5api-0.2.0}/.specify/scripts/bash/check-prerequisites.sh +0 -0
  58. {mt5api-0.0.4 → mt5api-0.2.0}/.specify/scripts/bash/common.sh +0 -0
  59. {mt5api-0.0.4 → mt5api-0.2.0}/.specify/scripts/bash/create-new-feature.sh +0 -0
  60. {mt5api-0.0.4 → mt5api-0.2.0}/.specify/scripts/bash/setup-plan.sh +0 -0
  61. {mt5api-0.0.4 → mt5api-0.2.0}/.specify/scripts/bash/update-agent-context.sh +0 -0
  62. {mt5api-0.0.4 → mt5api-0.2.0}/.specify/templates/agent-file-template.md +0 -0
  63. {mt5api-0.0.4 → mt5api-0.2.0}/.specify/templates/checklist-template.md +0 -0
  64. {mt5api-0.0.4 → mt5api-0.2.0}/.specify/templates/plan-template.md +0 -0
  65. {mt5api-0.0.4 → mt5api-0.2.0}/.specify/templates/spec-template.md +0 -0
  66. {mt5api-0.0.4 → mt5api-0.2.0}/.specify/templates/tasks-template.md +0 -0
  67. {mt5api-0.0.4 → mt5api-0.2.0}/CLAUDE.md +0 -0
  68. {mt5api-0.0.4 → mt5api-0.2.0}/LICENSE +0 -0
  69. {mt5api-0.0.4 → mt5api-0.2.0}/docs/api/index.md +0 -0
  70. {mt5api-0.0.4 → mt5api-0.2.0}/mkdocs.yml +0 -0
  71. {mt5api-0.0.4 → mt5api-0.2.0}/mt5api/__init__.py +0 -0
  72. {mt5api-0.0.4 → mt5api-0.2.0}/mt5api/__main__.py +0 -0
  73. {mt5api-0.0.4 → mt5api-0.2.0}/mt5api/auth.py +0 -0
  74. {mt5api-0.0.4 → mt5api-0.2.0}/mt5api/formatters.py +0 -0
  75. {mt5api-0.0.4 → mt5api-0.2.0}/mt5api/routers/account.py +0 -0
  76. {mt5api-0.0.4 → mt5api-0.2.0}/mt5api/routers/calc.py +0 -0
  77. {mt5api-0.0.4 → mt5api-0.2.0}/mt5api/routers/health.py +0 -0
  78. {mt5api-0.0.4 → mt5api-0.2.0}/mt5api/routers/history.py +0 -0
  79. {mt5api-0.0.4 → mt5api-0.2.0}/mt5api/routers/symbols.py +0 -0
  80. {mt5api-0.0.4 → mt5api-0.2.0}/specs/041-mt5-rest-api/contracts/openapi.yaml +0 -0
  81. {mt5api-0.0.4 → mt5api-0.2.0}/specs/041-mt5-rest-api/data-model.md +0 -0
  82. {mt5api-0.0.4 → mt5api-0.2.0}/specs/041-mt5-rest-api/plan.md +0 -0
  83. {mt5api-0.0.4 → mt5api-0.2.0}/specs/041-mt5-rest-api/quickstart.md +0 -0
  84. {mt5api-0.0.4 → mt5api-0.2.0}/specs/041-mt5-rest-api/research.md +0 -0
  85. {mt5api-0.0.4 → mt5api-0.2.0}/specs/041-mt5-rest-api/spec.md +0 -0
  86. {mt5api-0.0.4 → mt5api-0.2.0}/specs/041-mt5-rest-api/tasks.md +0 -0
  87. {mt5api-0.0.4 → mt5api-0.2.0}/specs/042-mt5-core-client/spec.md +0 -0
  88. {mt5api-0.0.4 → mt5api-0.2.0}/specs/043-mt5-dataframe-client/spec.md +0 -0
  89. {mt5api-0.0.4 → mt5api-0.2.0}/specs/044-mt5-trading-client/spec.md +0 -0
  90. {mt5api-0.0.4 → mt5api-0.2.0}/specs/045-mt5-utils/spec.md +0 -0
  91. {mt5api-0.0.4 → mt5api-0.2.0}/specs/046-mt5-api-service/spec.md +0 -0
  92. {mt5api-0.0.4 → mt5api-0.2.0}/specs/047-api-auth-rate-limit/spec.md +0 -0
  93. {mt5api-0.0.4 → mt5api-0.2.0}/specs/048-api-response-format/spec.md +0 -0
  94. {mt5api-0.0.4 → mt5api-0.2.0}/specs/049-api-routing-models/spec.md +0 -0
  95. {mt5api-0.0.4 → mt5api-0.2.0}/specs/050-api-runtime-deploy/spec.md +0 -0
  96. {mt5api-0.0.4 → mt5api-0.2.0}/specs/051-api-error-logging/spec.md +0 -0
  97. {mt5api-0.0.4 → mt5api-0.2.0}/specs/052-api-dependencies/spec.md +0 -0
  98. {mt5api-0.0.4 → mt5api-0.2.0}/tests/__init__.py +0 -0
  99. {mt5api-0.0.4 → mt5api-0.2.0}/tests/conftest.py +0 -0
  100. {mt5api-0.0.4 → mt5api-0.2.0}/tests/mt5_constants.py +0 -0
  101. {mt5api-0.0.4 → mt5api-0.2.0}/tests/test_account.py +0 -0
  102. {mt5api-0.0.4 → mt5api-0.2.0}/tests/test_auth.py +0 -0
  103. {mt5api-0.0.4 → mt5api-0.2.0}/tests/test_calc.py +0 -0
  104. {mt5api-0.0.4 → mt5api-0.2.0}/tests/test_cli.py +0 -0
  105. {mt5api-0.0.4 → mt5api-0.2.0}/tests/test_dependencies.py +0 -0
  106. {mt5api-0.0.4 → mt5api-0.2.0}/tests/test_formatters.py +0 -0
  107. {mt5api-0.0.4 → mt5api-0.2.0}/tests/test_health.py +0 -0
  108. {mt5api-0.0.4 → mt5api-0.2.0}/tests/test_history.py +0 -0
  109. {mt5api-0.0.4 → mt5api-0.2.0}/tests/test_integration.py +0 -0
  110. {mt5api-0.0.4 → mt5api-0.2.0}/tests/test_lifespan.py +0 -0
  111. {mt5api-0.0.4 → mt5api-0.2.0}/tests/test_market.py +0 -0
  112. {mt5api-0.0.4 → mt5api-0.2.0}/tests/test_models.py +0 -0
  113. {mt5api-0.0.4 → mt5api-0.2.0}/tests/test_symbols.py +0 -0
  114. {mt5api-0.0.4 → mt5api-0.2.0}/tests/test_trading.py +0 -0
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: local-qa
3
3
  description: Run local QA including formatting, linting, and testing for the repository. Use whenever any file has been updated.
4
- disable-model-invocation: true
4
+ disable-model-invocation: false
5
5
  ---
6
6
 
7
7
  # Local QA (format, lint, and test)
@@ -10,7 +10,7 @@ uv run pyright .
10
10
  uv run pytest
11
11
 
12
12
  # Markdown
13
- npx prettier --write './**/*.md'
13
+ npx -y prettier --write './**/*.md'
14
14
 
15
15
  # GitHub Actions
16
16
  case "${OSTYPE}" in
@@ -3,8 +3,8 @@ name: mt5api
3
3
  description: >-
4
4
  Query the MT5 API for account info, terminal status, health checks, symbol
5
5
  data, market data (OHLCV rates, ticks, market depth), open positions, pending
6
- orders, and trade history. Use when the user wants to interact with any mt5api
7
- endpoint.
6
+ orders, trade history, and reconnecting the MT5 terminal with new
7
+ credentials. Use when the user wants to interact with any mt5api endpoint.
8
8
  allowed-tools: Bash
9
9
  ---
10
10
 
@@ -30,6 +30,16 @@ if [ -n "${MT5API_SECRET_KEY:-}" ]; then
30
30
  fi
31
31
  ```
32
32
 
33
+ Login credentials for `/connection/login` are read from the environment so
34
+ the password is never hard-coded in a command:
35
+
36
+ | Variable | Description | Required for login |
37
+ | ----------------- | ------------------------------------------ | ------------------ |
38
+ | `MT5API_LOGIN` | Trading account login (integer) | yes |
39
+ | `MT5API_PASSWORD` | Trading account password | yes |
40
+ | `MT5API_SERVER` | Trading server name (e.g., `Broker-Demo`) | yes |
41
+ | `MT5API_TIMEOUT` | Connection timeout in milliseconds (`> 0`) | no |
42
+
33
43
  ## Response Formats
34
44
 
35
45
  All endpoints (except `/health`) return JSON by default. Request Parquet with
@@ -44,6 +54,11 @@ All endpoints (except `/health`) return JSON by default. Request Parquet with
44
54
  symbol or skipping DOM data.
45
55
  - Empty arrays from `/positions`, `/orders`, `/history/orders`, or
46
56
  `/history/deals` are valid results.
57
+ - `/connection/login` reconnects the shared MT5 client to a different account.
58
+ It shuts down the current connection and releases any active market-book
59
+ subscriptions before logging in. Never echo the password back to the user
60
+ and do not log it; the response only confirms `login`, `server`, `timeout`,
61
+ and `connected`.
47
62
 
48
63
  ---
49
64
 
@@ -77,6 +92,59 @@ curl -s "${AUTH_HEADER[@]}" \
77
92
 
78
93
  ---
79
94
 
95
+ ## Connection
96
+
97
+ ### Reconnect to MT5
98
+
99
+ Shut down the current MT5 client and reconnect with new credentials. Active
100
+ market-book subscriptions are released first. The call is serialized so
101
+ concurrent reconnect attempts do not race. The password is sent only in the
102
+ request body and is never echoed in the response.
103
+
104
+ ```bash
105
+ # Build JSON body from env vars; include timeout only when set
106
+ LOGIN_BODY=$(python3 -c "
107
+ import json, os, sys
108
+ body = {
109
+ 'login': int(os.environ['MT5API_LOGIN']),
110
+ 'password': os.environ['MT5API_PASSWORD'],
111
+ 'server': os.environ['MT5API_SERVER'],
112
+ }
113
+ t = os.environ.get('MT5API_TIMEOUT')
114
+ if t:
115
+ body['timeout'] = int(t)
116
+ print(json.dumps(body))
117
+ ")
118
+ curl -s -X POST "${AUTH_HEADER[@]}" \
119
+ -H 'Content-Type: application/json' \
120
+ -d "${LOGIN_BODY}" \
121
+ "${MT5API_URL}/connection/login" | python -m json.tool
122
+ ```
123
+
124
+ Request body:
125
+
126
+ | Field | Type | Required | Description |
127
+ | -------- | ------ | -------- | ------------------------------------------ |
128
+ | login | int | yes | Trading account login (positive integer) |
129
+ | password | string | yes | Trading account password (never echoed) |
130
+ | server | string | yes | Trading server name (e.g., `Broker-Demo`) |
131
+ | timeout | int | no | Connection timeout in milliseconds (`> 0`) |
132
+
133
+ Successful response (`200`):
134
+
135
+ | Field | Type | Description |
136
+ | --------- | ------ | -------------------------------------------- |
137
+ | login | int | Login that was used to connect |
138
+ | server | string | Trading server that was connected to |
139
+ | timeout | int? | Timeout in milliseconds if one was specified |
140
+ | connected | bool | `true` when the new connection succeeded |
141
+
142
+ On failure, MT5 errors surface as `503 Service Unavailable` with an RFC 7807
143
+ problem-details body. Never include the supplied password in any summary or
144
+ diagnostic you return to the user.
145
+
146
+ ---
147
+
80
148
  ## Account & Terminal
81
149
 
82
150
  ### Account Info
@@ -323,3 +391,6 @@ Either `(date_from AND date_to)` or `(ticket OR position)` must be provided.
323
391
  running or reachable.
324
392
  9. For historical queries, remind the user that either a date range or a
325
393
  ticket/position filter is required.
394
+ 10. For `/connection/login`, always send the password in the POST body and
395
+ never repeat it in any reply or log message. If the user asks you to
396
+ reconnect, confirm the target `login`/`server` before sending the request.
@@ -19,7 +19,6 @@ on:
19
19
  options:
20
20
  - lint-and-test
21
21
  - docs-deploy
22
- - release
23
22
  description: Choose the workflow to run
24
23
  default: lint-and-test
25
24
  permissions:
@@ -54,10 +53,7 @@ jobs:
54
53
  python-docs-deploy:
55
54
  if: >
56
55
  github.event_name == 'push'
57
- || (
58
- github.event_name == 'workflow_dispatch'
59
- && (inputs.workflow == 'docs-deploy' || inputs.workflow == 'release')
60
- )
56
+ || (github.event_name == 'workflow_dispatch' && inputs.workflow == 'docs-deploy')
61
57
  permissions:
62
58
  contents: write
63
59
  uses: dceoy/gh-actions-for-devops/.github/workflows/python-package-mkdocs-gh-deploy.yml@main # zizmor: ignore[unpinned-uses]
@@ -66,23 +62,6 @@ jobs:
66
62
  runs-on: ubuntu-slim
67
63
  secrets:
68
64
  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
69
- python-package-release:
70
- if: >
71
- github.event_name == 'push'
72
- || (
73
- github.event_name == 'workflow_dispatch'
74
- && (inputs.workflow == 'release' || inputs.workflow == 'lint-and-test')
75
- )
76
- permissions:
77
- contents: write
78
- id-token: write
79
- uses: dceoy/gh-actions-for-devops/.github/workflows/python-package-release-on-pypi-and-github.yml@main # zizmor: ignore[unpinned-uses]
80
- with:
81
- package-path: .
82
- create-releases: ${{ github.event_name == 'workflow_dispatch' && inputs.workflow == 'release' }}
83
- secrets:
84
- PYPI_API_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
85
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
86
65
  dependabot-auto-merge:
87
66
  if: >
88
67
  github.event_name == 'pull_request' && github.actor == 'dependabot[bot]'
@@ -0,0 +1,44 @@
1
+ ---
2
+ name: Release
3
+ on:
4
+ workflow_dispatch:
5
+ permissions:
6
+ contents: read
7
+ defaults:
8
+ run:
9
+ shell: bash -euo pipefail {0}
10
+ working-directory: .
11
+ jobs:
12
+ build-and-release:
13
+ permissions:
14
+ contents: write
15
+ id-token: write
16
+ uses: dceoy/gh-actions-for-devops/.github/workflows/python-package-release-on-pypi-and-github.yml@main # zizmor: ignore[unpinned-uses]
17
+ with:
18
+ package-path: .
19
+ create-github-release: true
20
+ publish-to-pypi: false
21
+ secrets:
22
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
23
+ publish-to-pypi:
24
+ name: Publish the Python 🐍 distribution 📦 to PyPI
25
+ if: >
26
+ startsWith(github.ref, 'refs/tags/')
27
+ needs:
28
+ - build-and-release
29
+ runs-on: ubuntu-latest
30
+ environment:
31
+ name: pypi
32
+ url: https://pypi.org/p/${{ needs.build-and-release.outputs.project-name }}
33
+ permissions:
34
+ id-token: write # IMPORTANT: mandatory for trusted publishing
35
+ steps:
36
+ - name: Download all the dists
37
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
38
+ with:
39
+ name: ${{ needs.build-and-release.outputs.distribution-artifact-name }}
40
+ path: dist/
41
+ - name: Publish distribution 📦 to PyPI
42
+ uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
43
+ with:
44
+ verbose: true
@@ -31,7 +31,7 @@
31
31
  ### Package Structure
32
32
 
33
33
  - `mt5api/`: Main FastAPI package.
34
- - `main.py`: App wiring, lifespan handling, middleware, CORS, and router registration.
34
+ - `main.py`: App wiring, lifespan handling, middleware, and router registration.
35
35
  - `__main__.py`: CLI entry point for launching the API from environment-backed configuration.
36
36
  - `config.py`: Environment-backed configuration normalization and validation.
37
37
  - `auth.py`: Optional API key authentication helpers.
@@ -50,6 +50,8 @@
50
50
  - Comprehensive linting with 35+ rule categories (ruff)
51
51
  - Test coverage tracking with 100% (pytest-cov)
52
52
  - Parametrized tests for input/result matrices using `pytest.mark.parametrize` (pytest)
53
+ - Test doubles (mocks, stubs) using `pytest_mock` for external dependencies (pytest-mock)
54
+ - Pydantic models for data validation and configuration
53
55
 
54
56
  ## Documentation Workflow
55
57
 
@@ -66,7 +68,7 @@
66
68
  ## Security & Configuration Tips
67
69
 
68
70
  - Do not commit real MT5 credentials or API keys.
69
- - Configure `MT5API_SECRET_KEY`, `MT5API_RATE_LIMIT`, `MT5API_CORS_ORIGINS`, `MT5API_ROUTER_PREFIX`, and `MT5API_LOG_LEVEL` through environment variables.
71
+ - Configure `MT5API_SECRET_KEY`, `MT5API_ROUTER_PREFIX`, and `MT5API_LOG_LEVEL` through environment variables.
70
72
  - Keep runtime configuration in the environment instead of hardcoding deployment values.
71
73
  - Authentication mode is fixed at process startup; cover both authenticated and unauthenticated behavior when changing auth-related code.
72
74
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mt5api
3
- Version: 0.0.4
3
+ Version: 0.2.0
4
4
  Summary: MetaTrader 5 REST API
5
5
  Project-URL: Repository, https://github.com/dceoy/mt5api.git
6
6
  Author-email: dceoy <dceoy@users.noreply.github.com>
@@ -24,7 +24,6 @@ Requires-Dist: pdmt5>=0.2.1
24
24
  Requires-Dist: pyarrow>=18.0.0
25
25
  Requires-Dist: python-jose[cryptography]>=3.3.0
26
26
  Requires-Dist: python-multipart>=0.0.9
27
- Requires-Dist: slowapi>=0.1.9
28
27
  Requires-Dist: uvicorn[standard]>=0.32.0
29
28
  Description-Content-Type: text/markdown
30
29
 
@@ -36,8 +35,8 @@ MetaTrader 5 REST API
36
35
 
37
36
  mt5api exposes MT5 market data, account info, trading history, and trading
38
37
  operations over HTTP. It uses the [`pdmt5`](https://github.com/dceoy/pdmt5)
39
- client internally and adds optional API-key auth, rate limiting, and
40
- JSON/Parquet response formatting.
38
+ client internally and adds optional API-key auth and JSON/Parquet response
39
+ formatting.
41
40
 
42
41
  The API server must run on Windows. The `MetaTrader5` Python package used by
43
42
  `pdmt5` is supported only on Windows, so you must host `mt5api` on a Windows
@@ -52,7 +51,7 @@ graph TB
52
51
 
53
52
  subgraph "Windows Host"
54
53
  subgraph "FastAPI Application"
55
- Middleware["Middleware Stack<br/>CORS · Logging · Error Handler · Rate Limiter"]
54
+ Middleware["Middleware Stack<br/>Logging · Error Handler"]
56
55
  Routers["Routers<br/>health · symbols · market · account · history · calc · trading"]
57
56
  Auth["API Key Security Dependency<br/>Security(api_key_header) · verify_api_key"]
58
57
  Deps["FastAPI Dependencies<br/>MT5 Client Singleton · Format Negotiation"]
@@ -75,8 +74,8 @@ graph TB
75
74
  - REST endpoints for symbols, market data, account info, orders, history,
76
75
  calculations, and trading operations
77
76
  - JSON and Apache Parquet responses (content negotiation)
78
- - Optional API key authentication with per-minute rate limiting
79
- - Structured JSON logging and configurable CORS
77
+ - Optional API key authentication
78
+ - Structured JSON logging
80
79
  - OpenAPI/Swagger docs built into the API
81
80
 
82
81
  ## Requirements
@@ -90,6 +89,20 @@ graph TB
90
89
 
91
90
  Install and run the API on the Windows machine where MetaTrader 5 is installed.
92
91
 
92
+ Install the latest release from PyPI:
93
+
94
+ ```console
95
+ pip install mt5api
96
+ ```
97
+
98
+ Or, when managing the project with `uv`, add it as a dependency:
99
+
100
+ ```console
101
+ uv add mt5api
102
+ ```
103
+
104
+ Alternatively, install from source:
105
+
93
106
  ```powershell
94
107
  git clone https://github.com/dceoy/mt5api.git
95
108
  cd mt5api
@@ -98,12 +111,24 @@ uv sync
98
111
 
99
112
  ## Running the API on Windows
100
113
 
114
+ After installing from PyPI:
115
+
101
116
  ```powershell
102
117
  $env:MT5API_SECRET_KEY = "your-secret-api-key" # Optional: omit to disable auth
103
118
  $env:MT5API_ROUTER_PREFIX = "/api/v1" # Optional: omit for root-level routes
104
- uv run uvicorn mt5api.main:app --host 0.0.0.0 --port 8000
119
+ python -m mt5api
105
120
  ```
106
121
 
122
+ `python -m mt5api` reads `MT5API_HOST`, `MT5API_PORT`, and `MT5API_LOG_LEVEL`
123
+ from the environment. You can also invoke `uvicorn` directly:
124
+
125
+ ```powershell
126
+ uvicorn mt5api.main:app --host 0.0.0.0 --port 8000
127
+ ```
128
+
129
+ If you cloned the source tree, prepend `uv run` to either command (for example,
130
+ `uv run uvicorn mt5api.main:app --host 0.0.0.0 --port 8000`).
131
+
107
132
  Docs:
108
133
 
109
134
  - Swagger UI: `http://localhost:8000/docs`
@@ -6,8 +6,8 @@ MetaTrader 5 REST API
6
6
 
7
7
  mt5api exposes MT5 market data, account info, trading history, and trading
8
8
  operations over HTTP. It uses the [`pdmt5`](https://github.com/dceoy/pdmt5)
9
- client internally and adds optional API-key auth, rate limiting, and
10
- JSON/Parquet response formatting.
9
+ client internally and adds optional API-key auth and JSON/Parquet response
10
+ formatting.
11
11
 
12
12
  The API server must run on Windows. The `MetaTrader5` Python package used by
13
13
  `pdmt5` is supported only on Windows, so you must host `mt5api` on a Windows
@@ -22,7 +22,7 @@ graph TB
22
22
 
23
23
  subgraph "Windows Host"
24
24
  subgraph "FastAPI Application"
25
- Middleware["Middleware Stack<br/>CORS · Logging · Error Handler · Rate Limiter"]
25
+ Middleware["Middleware Stack<br/>Logging · Error Handler"]
26
26
  Routers["Routers<br/>health · symbols · market · account · history · calc · trading"]
27
27
  Auth["API Key Security Dependency<br/>Security(api_key_header) · verify_api_key"]
28
28
  Deps["FastAPI Dependencies<br/>MT5 Client Singleton · Format Negotiation"]
@@ -45,8 +45,8 @@ graph TB
45
45
  - REST endpoints for symbols, market data, account info, orders, history,
46
46
  calculations, and trading operations
47
47
  - JSON and Apache Parquet responses (content negotiation)
48
- - Optional API key authentication with per-minute rate limiting
49
- - Structured JSON logging and configurable CORS
48
+ - Optional API key authentication
49
+ - Structured JSON logging
50
50
  - OpenAPI/Swagger docs built into the API
51
51
 
52
52
  ## Requirements
@@ -60,6 +60,20 @@ graph TB
60
60
 
61
61
  Install and run the API on the Windows machine where MetaTrader 5 is installed.
62
62
 
63
+ Install the latest release from PyPI:
64
+
65
+ ```console
66
+ pip install mt5api
67
+ ```
68
+
69
+ Or, when managing the project with `uv`, add it as a dependency:
70
+
71
+ ```console
72
+ uv add mt5api
73
+ ```
74
+
75
+ Alternatively, install from source:
76
+
63
77
  ```powershell
64
78
  git clone https://github.com/dceoy/mt5api.git
65
79
  cd mt5api
@@ -68,12 +82,24 @@ uv sync
68
82
 
69
83
  ## Running the API on Windows
70
84
 
85
+ After installing from PyPI:
86
+
71
87
  ```powershell
72
88
  $env:MT5API_SECRET_KEY = "your-secret-api-key" # Optional: omit to disable auth
73
89
  $env:MT5API_ROUTER_PREFIX = "/api/v1" # Optional: omit for root-level routes
74
- uv run uvicorn mt5api.main:app --host 0.0.0.0 --port 8000
90
+ python -m mt5api
75
91
  ```
76
92
 
93
+ `python -m mt5api` reads `MT5API_HOST`, `MT5API_PORT`, and `MT5API_LOG_LEVEL`
94
+ from the environment. You can also invoke `uvicorn` directly:
95
+
96
+ ```powershell
97
+ uvicorn mt5api.main:app --host 0.0.0.0 --port 8000
98
+ ```
99
+
100
+ If you cloned the source tree, prepend `uv run` to either command (for example,
101
+ `uv run uvicorn mt5api.main:app --host 0.0.0.0 --port 8000`).
102
+
77
103
  Docs:
78
104
 
79
105
  - Swagger UI: `http://localhost:8000/docs`
@@ -36,9 +36,7 @@ nssm install mt5api
36
36
  # Optional: set MT5API_SECRET_KEY only when you want to require X-API-Key headers.
37
37
  MT5API_SECRET_KEY=your-secret-api-key
38
38
  MT5API_LOG_LEVEL=INFO
39
- MT5API_RATE_LIMIT=100
40
39
  MT5API_MAX_MARKET_BOOK_SUBSCRIPTIONS=100
41
- MT5API_CORS_ORIGINS=*
42
40
  MT5API_ROUTER_PREFIX=/api/v1
43
41
  ```
44
42
 
@@ -30,9 +30,7 @@ Set the optional API key and other limits via environment variables:
30
30
  ```powershell
31
31
  $env:MT5API_SECRET_KEY = "your-secret-api-key" # Optional: omit to disable auth
32
32
  $env:MT5API_LOG_LEVEL = "INFO"
33
- $env:MT5API_RATE_LIMIT = "100"
34
33
  $env:MT5API_MAX_MARKET_BOOK_SUBSCRIPTIONS = "100"
35
- $env:MT5API_CORS_ORIGINS = "*"
36
34
  $env:MT5API_ROUTER_PREFIX = "/api/v1" # Optional: omit for root-level routes
37
35
  ```
38
36
 
@@ -70,10 +68,7 @@ disabled and those endpoints are accessible without authorization.
70
68
  curl -H "X-API-Key: your-secret-api-key" "http://windows-host:8000/symbols"
71
69
  ```
72
70
 
73
- ## Rate Limiting
74
-
75
- Rate limiting uses `slowapi` with a default limit of `100/minute`. Set
76
- `MT5API_RATE_LIMIT` to an integer for a different per-minute cap.
71
+ ## Subscription Limits
77
72
 
78
73
  Active market-book subscriptions are capped at `100` symbols by default. Set
79
74
  `MT5API_MAX_MARKET_BOOK_SUBSCRIPTIONS` to a positive integer to adjust that
@@ -121,9 +116,9 @@ If `MT5API_ROUTER_PREFIX` is configured, prepend it to each API route below.
121
116
  - `GET /rates/range` (`symbol`, `timeframe`, `date_from`, `date_to`, `format`)
122
117
  - `GET /ticks/from` (`symbol`, `date_from`, `count`, `flags`, `format`)
123
118
  - `GET /ticks/range` (`symbol`, `date_from`, `date_to`, `flags`, `format`)
124
- - `GET /market-book/{symbol}` (`format`) — Market depth (DOM)
125
- - `POST /market-book/{symbol}/subscribe` — Subscribe to DOM events
126
- - `POST /market-book/{symbol}/unsubscribe` — Unsubscribe from DOM events
119
+ - `GET /market-book/{symbol}` (`format`) — Market depth (DOM) _(experimental)_
120
+ - `POST /market-book/{symbol}/subscribe` — Subscribe to DOM events _(experimental)_
121
+ - `POST /market-book/{symbol}/unsubscribe` — Unsubscribe from DOM events _(experimental)_
127
122
 
128
123
  ### Calculations
129
124
 
@@ -167,6 +162,14 @@ structure](https://www.mql5.com/en/docs/constants/structures/mqltraderequest),
167
162
  with typed validation for core fields such as `action`, `symbol`, `volume`,
168
163
  `type`, and `price`.
169
164
 
165
+ ### Connection
166
+
167
+ - `POST /connection/login` (body: `{"login": ..., "password": "...",
168
+ "server": "...", "timeout": ...}`) — Reconnect the MT5 terminal with the
169
+ supplied credentials. Any active market-book subscriptions are released and
170
+ the previous MT5 client is shut down before the new connection is
171
+ established. The supplied password is never echoed in responses or logs.
172
+
170
173
  ## Response Formatter Utilities
171
174
 
172
175
  If you are extending the API with custom endpoints, use the formatter helpers
@@ -296,6 +299,14 @@ curl -X POST -H "X-API-Key: your-secret-api-key" -H "Content-Type: application/j
296
299
  "http://windows-host:8000/order/check"
297
300
  ```
298
301
 
302
+ ### Reconnect to MT5
303
+
304
+ ```console
305
+ curl -X POST -H "X-API-Key: your-secret-api-key" -H "Content-Type: application/json" \
306
+ -d '{"login": 12345678, "password": "s3cret", "server": "MetaQuotes-Demo", "timeout": 60000}' \
307
+ "http://windows-host:8000/connection/login"
308
+ ```
309
+
299
310
  ## Error Responses
300
311
 
301
312
  Errors follow RFC 7807 Problem Details:
@@ -315,9 +326,8 @@ Errors follow RFC 7807 Problem Details:
315
326
  Minimum security posture for deployments:
316
327
 
317
328
  - Set `MT5API_SECRET_KEY` to enable API key authentication when needed
318
- - Rate limiting enabled (`MT5API_RATE_LIMIT`)
329
+ - Configure rate limiting at the reverse proxy or API gateway level
319
330
  - Run behind HTTPS in production
320
- - Restrict CORS origins (`MT5API_CORS_ORIGINS`) for public deployments
321
331
  - Restrict access to operational endpoints (`/order/check`,
322
332
  `/symbols/{symbol}/select`, `/market-book/{symbol}/subscribe`,
323
333
  `/market-book/{symbol}/unsubscribe`) to trusted clients only
@@ -7,7 +7,7 @@ trading operations.
7
7
 
8
8
  mt5api exposes MT5 data and trading operations over HTTP using FastAPI. It
9
9
  relies on the underlying MT5 client library for connectivity and adds optional
10
- authentication, rate limiting, and response formatting suitable for analytics
10
+ authentication and response formatting suitable for analytics
11
11
  workflows.
12
12
 
13
13
  The API server must run on Windows because the `MetaTrader5` Python package is
@@ -19,8 +19,8 @@ logged in. API clients can connect from any operating system.
19
19
  - REST endpoints for symbols, market data, account info, orders, history,
20
20
  calculations, and trading operations
21
21
  - JSON and Apache Parquet responses
22
- - Optional API key authentication and rate limiting
23
- - Structured JSON logging and configurable CORS
22
+ - Optional API key authentication
23
+ - Structured JSON logging
24
24
  - OpenAPI/Swagger docs built in
25
25
 
26
26
  ## Requirements
@@ -6,18 +6,14 @@ import os
6
6
  import re
7
7
 
8
8
  from .constants import (
9
- DEFAULT_API_CORS_ORIGINS,
10
9
  DEFAULT_API_HOST,
11
10
  DEFAULT_API_LOG_LEVEL,
12
- DEFAULT_API_RATE_LIMIT,
13
11
  DEFAULT_API_ROUTER_PREFIX,
14
12
  DEFAULT_MAX_MARKET_BOOK_SUBSCRIPTIONS,
15
- ENV_MT5API_CORS_ORIGINS,
16
13
  ENV_MT5API_HOST,
17
14
  ENV_MT5API_LOG_LEVEL,
18
15
  ENV_MT5API_MAX_MARKET_BOOK_SUBSCRIPTIONS,
19
16
  ENV_MT5API_PORT,
20
- ENV_MT5API_RATE_LIMIT,
21
17
  ENV_MT5API_ROUTER_PREFIX,
22
18
  ENV_MT5API_SECRET_KEY,
23
19
  )
@@ -81,24 +77,6 @@ def get_configured_api_log_level() -> str:
81
77
  return os.getenv(ENV_MT5API_LOG_LEVEL, DEFAULT_API_LOG_LEVEL)
82
78
 
83
79
 
84
- def get_configured_api_rate_limit() -> str:
85
- """Get the configured API rate limit string.
86
-
87
- Returns:
88
- Raw per-minute rate-limit string from configuration.
89
- """
90
- return os.getenv(ENV_MT5API_RATE_LIMIT, str(DEFAULT_API_RATE_LIMIT))
91
-
92
-
93
- def get_configured_api_cors_origins() -> str:
94
- """Get the configured CORS origins string.
95
-
96
- Returns:
97
- Raw CORS origins configuration string.
98
- """
99
- return os.getenv(ENV_MT5API_CORS_ORIGINS, DEFAULT_API_CORS_ORIGINS)
100
-
101
-
102
80
  def get_configured_api_router_prefix() -> str:
103
81
  """Get the configured API router prefix.
104
82
 
@@ -20,8 +20,6 @@ MAX_MARKET_BOOK_SUBSCRIPTIONS_STATE_KEY = "max_market_book_subscriptions"
20
20
  ENV_MT5API_HOST = "MT5API_HOST"
21
21
  ENV_MT5API_PORT = "MT5API_PORT"
22
22
  ENV_MT5API_LOG_LEVEL = "MT5API_LOG_LEVEL"
23
- ENV_MT5API_RATE_LIMIT = "MT5API_RATE_LIMIT"
24
- ENV_MT5API_CORS_ORIGINS = "MT5API_CORS_ORIGINS"
25
23
  ENV_MT5API_ROUTER_PREFIX = "MT5API_ROUTER_PREFIX"
26
24
  ENV_MT5API_MAX_MARKET_BOOK_SUBSCRIPTIONS = "MT5API_MAX_MARKET_BOOK_SUBSCRIPTIONS"
27
25
  ENV_MT5API_SECRET_KEY = "MT5API_SECRET_KEY" # noqa: S105
@@ -29,8 +27,6 @@ ENV_MT5API_SECRET_KEY = "MT5API_SECRET_KEY" # noqa: S105
29
27
  DEFAULT_API_HOST = "0.0.0.0" # noqa: S104
30
28
  DEFAULT_API_PORT = 8000
31
29
  DEFAULT_API_LOG_LEVEL = "INFO"
32
- DEFAULT_API_RATE_LIMIT = 100
33
- DEFAULT_API_CORS_ORIGINS = "*"
34
30
  DEFAULT_API_ROUTER_PREFIX = ""
35
31
  DEFAULT_MAX_MARKET_BOOK_SUBSCRIPTIONS = 100
36
32
  MAX_API_PORT = 65535