fidelity-trader-api 0.1.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 (213) hide show
  1. fidelity_trader_api-0.1.0/.claude/agents/capture-analyst.md +79 -0
  2. fidelity_trader_api-0.1.0/.claude/agents/docker-builder.md +237 -0
  3. fidelity_trader_api-0.1.0/.claude/agents/route-builder.md +181 -0
  4. fidelity_trader_api-0.1.0/.claude/agents/sdk-implementer.md +168 -0
  5. fidelity_trader_api-0.1.0/.claude/agents/service-reviewer.md +157 -0
  6. fidelity_trader_api-0.1.0/.claude/agents/service-scaffolder.md +158 -0
  7. fidelity_trader_api-0.1.0/.claude/agents/service-tester.md +209 -0
  8. fidelity_trader_api-0.1.0/.claude/agents/streaming-builder.md +223 -0
  9. fidelity_trader_api-0.1.0/.dockerignore +14 -0
  10. fidelity_trader_api-0.1.0/.github/workflows/ci.yml +31 -0
  11. fidelity_trader_api-0.1.0/.github/workflows/publish.yml +60 -0
  12. fidelity_trader_api-0.1.0/.gitignore +12 -0
  13. fidelity_trader_api-0.1.0/CLAUDE.md +159 -0
  14. fidelity_trader_api-0.1.0/LICENSE +191 -0
  15. fidelity_trader_api-0.1.0/PKG-INFO +830 -0
  16. fidelity_trader_api-0.1.0/README.md +792 -0
  17. fidelity_trader_api-0.1.0/data/ftservice.db +0 -0
  18. fidelity_trader_api-0.1.0/docker/.env.example +35 -0
  19. fidelity_trader_api-0.1.0/docker/Dockerfile +26 -0
  20. fidelity_trader_api-0.1.0/docker/docker-compose.yml +19 -0
  21. fidelity_trader_api-0.1.0/docs/BACKLOG.md +175 -0
  22. fidelity_trader_api-0.1.0/docs/DECISIONS.md +159 -0
  23. fidelity_trader_api-0.1.0/docs/PRODUCT_VISION.md +259 -0
  24. fidelity_trader_api-0.1.0/docs/SERVICE_PLAN.md +618 -0
  25. fidelity_trader_api-0.1.0/docs/captures/2026-03-30-websocket-streaming.md +137 -0
  26. fidelity_trader_api-0.1.0/docs/superpowers/plans/2026-03-30-fidelity-trader-sdk.md +2096 -0
  27. fidelity_trader_api-0.1.0/examples/full_walkthrough.py +822 -0
  28. fidelity_trader_api-0.1.0/examples/live_streaming.py +136 -0
  29. fidelity_trader_api-0.1.0/examples/live_test.py +108 -0
  30. fidelity_trader_api-0.1.0/examples/login.py +8 -0
  31. fidelity_trader_api-0.1.0/examples/mdds_experiment.py +222 -0
  32. fidelity_trader_api-0.1.0/examples/test_all_data_types.py +225 -0
  33. fidelity_trader_api-0.1.0/pyproject.toml +67 -0
  34. fidelity_trader_api-0.1.0/service/__init__.py +3 -0
  35. fidelity_trader_api-0.1.0/service/__main__.py +13 -0
  36. fidelity_trader_api-0.1.0/service/app.py +144 -0
  37. fidelity_trader_api-0.1.0/service/auth/__init__.py +0 -0
  38. fidelity_trader_api-0.1.0/service/auth/api_key.py +22 -0
  39. fidelity_trader_api-0.1.0/service/auth/middleware.py +64 -0
  40. fidelity_trader_api-0.1.0/service/config.py +17 -0
  41. fidelity_trader_api-0.1.0/service/dependencies.py +31 -0
  42. fidelity_trader_api-0.1.0/service/models/__init__.py +0 -0
  43. fidelity_trader_api-0.1.0/service/models/requests.py +43 -0
  44. fidelity_trader_api-0.1.0/service/models/responses.py +39 -0
  45. fidelity_trader_api-0.1.0/service/routes/__init__.py +0 -0
  46. fidelity_trader_api-0.1.0/service/routes/accounts.py +92 -0
  47. fidelity_trader_api-0.1.0/service/routes/auth.py +62 -0
  48. fidelity_trader_api-0.1.0/service/routes/market_data.py +71 -0
  49. fidelity_trader_api-0.1.0/service/routes/orders.py +187 -0
  50. fidelity_trader_api-0.1.0/service/routes/preferences.py +59 -0
  51. fidelity_trader_api-0.1.0/service/routes/reference.py +26 -0
  52. fidelity_trader_api-0.1.0/service/routes/research.py +79 -0
  53. fidelity_trader_api-0.1.0/service/routes/service.py +28 -0
  54. fidelity_trader_api-0.1.0/service/routes/streaming.py +64 -0
  55. fidelity_trader_api-0.1.0/service/routes/watchlists.py +109 -0
  56. fidelity_trader_api-0.1.0/service/session/__init__.py +0 -0
  57. fidelity_trader_api-0.1.0/service/session/keepalive.py +48 -0
  58. fidelity_trader_api-0.1.0/service/session/manager.py +77 -0
  59. fidelity_trader_api-0.1.0/service/session/store.py +114 -0
  60. fidelity_trader_api-0.1.0/service/streaming/__init__.py +0 -0
  61. fidelity_trader_api-0.1.0/service/streaming/manager.py +202 -0
  62. fidelity_trader_api-0.1.0/service/streaming/sse.py +55 -0
  63. fidelity_trader_api-0.1.0/service/streaming/ws.py +53 -0
  64. fidelity_trader_api-0.1.0/src/fidelity_trader/__init__.py +22 -0
  65. fidelity_trader_api-0.1.0/src/fidelity_trader/_http.py +75 -0
  66. fidelity_trader_api-0.1.0/src/fidelity_trader/alerts/__init__.py +4 -0
  67. fidelity_trader_api-0.1.0/src/fidelity_trader/alerts/price_triggers.py +140 -0
  68. fidelity_trader_api-0.1.0/src/fidelity_trader/alerts/subscription.py +147 -0
  69. fidelity_trader_api-0.1.0/src/fidelity_trader/async_client.py +216 -0
  70. fidelity_trader_api-0.1.0/src/fidelity_trader/auth/__init__.py +3 -0
  71. fidelity_trader_api-0.1.0/src/fidelity_trader/auth/auto_refresh.py +120 -0
  72. fidelity_trader_api-0.1.0/src/fidelity_trader/auth/security_context.py +26 -0
  73. fidelity_trader_api-0.1.0/src/fidelity_trader/auth/session.py +211 -0
  74. fidelity_trader_api-0.1.0/src/fidelity_trader/auth/session_keepalive.py +38 -0
  75. fidelity_trader_api-0.1.0/src/fidelity_trader/cli/__init__.py +3 -0
  76. fidelity_trader_api-0.1.0/src/fidelity_trader/cli/_app.py +67 -0
  77. fidelity_trader_api-0.1.0/src/fidelity_trader/cli/_auth.py +145 -0
  78. fidelity_trader_api-0.1.0/src/fidelity_trader/cli/_config.py +25 -0
  79. fidelity_trader_api-0.1.0/src/fidelity_trader/cli/_errors.py +50 -0
  80. fidelity_trader_api-0.1.0/src/fidelity_trader/cli/_market_data.py +187 -0
  81. fidelity_trader_api-0.1.0/src/fidelity_trader/cli/_options.py +303 -0
  82. fidelity_trader_api-0.1.0/src/fidelity_trader/cli/_orders.py +293 -0
  83. fidelity_trader_api-0.1.0/src/fidelity_trader/cli/_output.py +109 -0
  84. fidelity_trader_api-0.1.0/src/fidelity_trader/cli/_portfolio.py +191 -0
  85. fidelity_trader_api-0.1.0/src/fidelity_trader/cli/_research.py +135 -0
  86. fidelity_trader_api-0.1.0/src/fidelity_trader/cli/_session.py +139 -0
  87. fidelity_trader_api-0.1.0/src/fidelity_trader/cli/_stream.py +204 -0
  88. fidelity_trader_api-0.1.0/src/fidelity_trader/client.py +162 -0
  89. fidelity_trader_api-0.1.0/src/fidelity_trader/credentials.py +182 -0
  90. fidelity_trader_api-0.1.0/src/fidelity_trader/exceptions.py +21 -0
  91. fidelity_trader_api-0.1.0/src/fidelity_trader/market_data/__init__.py +4 -0
  92. fidelity_trader_api-0.1.0/src/fidelity_trader/market_data/chart.py +105 -0
  93. fidelity_trader_api-0.1.0/src/fidelity_trader/market_data/fastquote.py +48 -0
  94. fidelity_trader_api-0.1.0/src/fidelity_trader/models/__init__.py +3 -0
  95. fidelity_trader_api-0.1.0/src/fidelity_trader/models/_parsers.py +39 -0
  96. fidelity_trader_api-0.1.0/src/fidelity_trader/models/account.py +15 -0
  97. fidelity_trader_api-0.1.0/src/fidelity_trader/models/account_detail.py +119 -0
  98. fidelity_trader_api-0.1.0/src/fidelity_trader/models/alerts.py +196 -0
  99. fidelity_trader_api-0.1.0/src/fidelity_trader/models/analytics.py +87 -0
  100. fidelity_trader_api-0.1.0/src/fidelity_trader/models/auth.py +40 -0
  101. fidelity_trader_api-0.1.0/src/fidelity_trader/models/available_market.py +97 -0
  102. fidelity_trader_api-0.1.0/src/fidelity_trader/models/balance.py +407 -0
  103. fidelity_trader_api-0.1.0/src/fidelity_trader/models/cancel_order.py +49 -0
  104. fidelity_trader_api-0.1.0/src/fidelity_trader/models/cancel_replace.py +263 -0
  105. fidelity_trader_api-0.1.0/src/fidelity_trader/models/chart.py +96 -0
  106. fidelity_trader_api-0.1.0/src/fidelity_trader/models/closed_position.py +252 -0
  107. fidelity_trader_api-0.1.0/src/fidelity_trader/models/conditional_order.py +357 -0
  108. fidelity_trader_api-0.1.0/src/fidelity_trader/models/equity_order.py +271 -0
  109. fidelity_trader_api-0.1.0/src/fidelity_trader/models/fastquote.py +222 -0
  110. fidelity_trader_api-0.1.0/src/fidelity_trader/models/holiday_calendar.py +42 -0
  111. fidelity_trader_api-0.1.0/src/fidelity_trader/models/loaned_securities.py +115 -0
  112. fidelity_trader_api-0.1.0/src/fidelity_trader/models/option_order.py +355 -0
  113. fidelity_trader_api-0.1.0/src/fidelity_trader/models/option_summary.py +268 -0
  114. fidelity_trader_api-0.1.0/src/fidelity_trader/models/order.py +182 -0
  115. fidelity_trader_api-0.1.0/src/fidelity_trader/models/position.py +206 -0
  116. fidelity_trader_api-0.1.0/src/fidelity_trader/models/preferences.py +47 -0
  117. fidelity_trader_api-0.1.0/src/fidelity_trader/models/price_trigger.py +214 -0
  118. fidelity_trader_api-0.1.0/src/fidelity_trader/models/research.py +118 -0
  119. fidelity_trader_api-0.1.0/src/fidelity_trader/models/screener.py +93 -0
  120. fidelity_trader_api-0.1.0/src/fidelity_trader/models/search.py +33 -0
  121. fidelity_trader_api-0.1.0/src/fidelity_trader/models/security_context.py +69 -0
  122. fidelity_trader_api-0.1.0/src/fidelity_trader/models/single_option_order.py +284 -0
  123. fidelity_trader_api-0.1.0/src/fidelity_trader/models/staged_order.py +80 -0
  124. fidelity_trader_api-0.1.0/src/fidelity_trader/models/streaming.py +13 -0
  125. fidelity_trader_api-0.1.0/src/fidelity_trader/models/tax_lot.py +134 -0
  126. fidelity_trader_api-0.1.0/src/fidelity_trader/models/transaction.py +153 -0
  127. fidelity_trader_api-0.1.0/src/fidelity_trader/models/watchlist.py +121 -0
  128. fidelity_trader_api-0.1.0/src/fidelity_trader/orders/__init__.py +8 -0
  129. fidelity_trader_api-0.1.0/src/fidelity_trader/orders/cancel.py +61 -0
  130. fidelity_trader_api-0.1.0/src/fidelity_trader/orders/cancel_replace.py +68 -0
  131. fidelity_trader_api-0.1.0/src/fidelity_trader/orders/conditional.py +73 -0
  132. fidelity_trader_api-0.1.0/src/fidelity_trader/orders/equity.py +65 -0
  133. fidelity_trader_api-0.1.0/src/fidelity_trader/orders/options.py +75 -0
  134. fidelity_trader_api-0.1.0/src/fidelity_trader/orders/single_option.py +71 -0
  135. fidelity_trader_api-0.1.0/src/fidelity_trader/orders/staged.py +69 -0
  136. fidelity_trader_api-0.1.0/src/fidelity_trader/orders/status.py +49 -0
  137. fidelity_trader_api-0.1.0/src/fidelity_trader/portfolio/__init__.py +7 -0
  138. fidelity_trader_api-0.1.0/src/fidelity_trader/portfolio/accounts.py +52 -0
  139. fidelity_trader_api-0.1.0/src/fidelity_trader/portfolio/balances.py +74 -0
  140. fidelity_trader_api-0.1.0/src/fidelity_trader/portfolio/closed_positions.py +68 -0
  141. fidelity_trader_api-0.1.0/src/fidelity_trader/portfolio/loaned_securities.py +29 -0
  142. fidelity_trader_api-0.1.0/src/fidelity_trader/portfolio/option_summary.py +37 -0
  143. fidelity_trader_api-0.1.0/src/fidelity_trader/portfolio/positions.py +63 -0
  144. fidelity_trader_api-0.1.0/src/fidelity_trader/portfolio/tax_lots.py +34 -0
  145. fidelity_trader_api-0.1.0/src/fidelity_trader/portfolio/transactions.py +68 -0
  146. fidelity_trader_api-0.1.0/src/fidelity_trader/reference/__init__.py +0 -0
  147. fidelity_trader_api-0.1.0/src/fidelity_trader/reference/holiday_calendar.py +26 -0
  148. fidelity_trader_api-0.1.0/src/fidelity_trader/reference/markets.py +29 -0
  149. fidelity_trader_api-0.1.0/src/fidelity_trader/research/__init__.py +6 -0
  150. fidelity_trader_api-0.1.0/src/fidelity_trader/research/analytics.py +49 -0
  151. fidelity_trader_api-0.1.0/src/fidelity_trader/research/data.py +44 -0
  152. fidelity_trader_api-0.1.0/src/fidelity_trader/research/screener.py +111 -0
  153. fidelity_trader_api-0.1.0/src/fidelity_trader/research/search.py +25 -0
  154. fidelity_trader_api-0.1.0/src/fidelity_trader/retry.py +105 -0
  155. fidelity_trader_api-0.1.0/src/fidelity_trader/settings/__init__.py +0 -0
  156. fidelity_trader_api-0.1.0/src/fidelity_trader/settings/preferences.py +89 -0
  157. fidelity_trader_api-0.1.0/src/fidelity_trader/streaming/__init__.py +4 -0
  158. fidelity_trader_api-0.1.0/src/fidelity_trader/streaming/mdds.py +330 -0
  159. fidelity_trader_api-0.1.0/src/fidelity_trader/streaming/mdds_fields.py +152 -0
  160. fidelity_trader_api-0.1.0/src/fidelity_trader/streaming/news.py +25 -0
  161. fidelity_trader_api-0.1.0/src/fidelity_trader/trading/__init__.py +0 -0
  162. fidelity_trader_api-0.1.0/src/fidelity_trader/watchlists/__init__.py +3 -0
  163. fidelity_trader_api-0.1.0/src/fidelity_trader/watchlists/watchlists.py +88 -0
  164. fidelity_trader_api-0.1.0/tests/__init__.py +0 -0
  165. fidelity_trader_api-0.1.0/tests/conftest.py +30 -0
  166. fidelity_trader_api-0.1.0/tests/test_account_discovery.py +501 -0
  167. fidelity_trader_api-0.1.0/tests/test_alerts.py +728 -0
  168. fidelity_trader_api-0.1.0/tests/test_analytics.py +465 -0
  169. fidelity_trader_api-0.1.0/tests/test_async_client.py +329 -0
  170. fidelity_trader_api-0.1.0/tests/test_auth.py +80 -0
  171. fidelity_trader_api-0.1.0/tests/test_auto_refresh.py +288 -0
  172. fidelity_trader_api-0.1.0/tests/test_available_markets.py +459 -0
  173. fidelity_trader_api-0.1.0/tests/test_balances.py +1153 -0
  174. fidelity_trader_api-0.1.0/tests/test_cancel_orders.py +189 -0
  175. fidelity_trader_api-0.1.0/tests/test_cancel_replace.py +766 -0
  176. fidelity_trader_api-0.1.0/tests/test_chart.py +452 -0
  177. fidelity_trader_api-0.1.0/tests/test_cli.py +425 -0
  178. fidelity_trader_api-0.1.0/tests/test_cli_market.py +398 -0
  179. fidelity_trader_api-0.1.0/tests/test_cli_orders.py +588 -0
  180. fidelity_trader_api-0.1.0/tests/test_client.py +280 -0
  181. fidelity_trader_api-0.1.0/tests/test_closed_positions.py +673 -0
  182. fidelity_trader_api-0.1.0/tests/test_conditional_orders.py +822 -0
  183. fidelity_trader_api-0.1.0/tests/test_csrf.py +38 -0
  184. fidelity_trader_api-0.1.0/tests/test_dry_run.py +265 -0
  185. fidelity_trader_api-0.1.0/tests/test_equity_orders.py +486 -0
  186. fidelity_trader_api-0.1.0/tests/test_fastquote.py +378 -0
  187. fidelity_trader_api-0.1.0/tests/test_holiday_calendar.py +293 -0
  188. fidelity_trader_api-0.1.0/tests/test_http.py +30 -0
  189. fidelity_trader_api-0.1.0/tests/test_loaned_securities.py +224 -0
  190. fidelity_trader_api-0.1.0/tests/test_mdds.py +1241 -0
  191. fidelity_trader_api-0.1.0/tests/test_models.py +137 -0
  192. fidelity_trader_api-0.1.0/tests/test_option_orders.py +583 -0
  193. fidelity_trader_api-0.1.0/tests/test_option_summary.py +640 -0
  194. fidelity_trader_api-0.1.0/tests/test_orders.py +581 -0
  195. fidelity_trader_api-0.1.0/tests/test_positions.py +501 -0
  196. fidelity_trader_api-0.1.0/tests/test_preferences.py +221 -0
  197. fidelity_trader_api-0.1.0/tests/test_price_triggers.py +880 -0
  198. fidelity_trader_api-0.1.0/tests/test_research.py +506 -0
  199. fidelity_trader_api-0.1.0/tests/test_retry.py +406 -0
  200. fidelity_trader_api-0.1.0/tests/test_screener.py +572 -0
  201. fidelity_trader_api-0.1.0/tests/test_search.py +324 -0
  202. fidelity_trader_api-0.1.0/tests/test_security_context.py +173 -0
  203. fidelity_trader_api-0.1.0/tests/test_service_routes_core.py +305 -0
  204. fidelity_trader_api-0.1.0/tests/test_service_routes_data.py +297 -0
  205. fidelity_trader_api-0.1.0/tests/test_service_scaffold.py +355 -0
  206. fidelity_trader_api-0.1.0/tests/test_service_streaming.py +416 -0
  207. fidelity_trader_api-0.1.0/tests/test_session_keepalive.py +238 -0
  208. fidelity_trader_api-0.1.0/tests/test_single_option_orders.py +646 -0
  209. fidelity_trader_api-0.1.0/tests/test_staged_orders.py +301 -0
  210. fidelity_trader_api-0.1.0/tests/test_streaming.py +140 -0
  211. fidelity_trader_api-0.1.0/tests/test_tax_lots.py +399 -0
  212. fidelity_trader_api-0.1.0/tests/test_transactions.py +548 -0
  213. fidelity_trader_api-0.1.0/tests/test_watchlists.py +645 -0
@@ -0,0 +1,79 @@
1
+ ---
2
+ name: capture-analyst
3
+ description: Analyzes mitmproxy capture files to discover and document Fidelity API endpoints. Use when the user has completed a new mitmproxy capture session and needs endpoints extracted, documented, and queued for implementation.
4
+ tools: Read, Glob, Grep, Bash, Write
5
+ model: inherit
6
+ ---
7
+
8
+ You analyze mitmproxy capture files to discover and document Fidelity Trader+ API endpoints.
9
+
10
+ ## Context
11
+
12
+ This project is the `fidelity-trader-sdk` — an unofficial Python SDK that replicates Fidelity Trader+ desktop API calls via reverse-engineered mitmproxy captures. The SDK currently has **31 API modules** across 7+ hosts. Your job is to analyze new captures, extract undocumented endpoints, and prepare implementation specs.
13
+
14
+ ## Capture Files
15
+
16
+ Stored in `~/fidelity_*.flow`. Current inventory:
17
+ - `fidelity_capture.flow` — Login, positions, balances, accounts, preferences
18
+ - `fidelity_portfolio_capture.flow` — Transactions, option summary, closed positions, loaned securities, watchlists
19
+ - `fidelity_market_hours_capture.flow` — Orders (equity/option/cancel), tax lots, available markets, analytics, chart, montage
20
+ - `fidelity_2fa_capture.flow` — TOTP 2FA, option chain, alerts, search, news auth
21
+ - `fidelity_websocket_capture.flow` — MDDS WebSocket, holiday calendar, price triggers, staged orders
22
+ - `fidelity_ts_l2_capture.flow` — Time & Sales / L2 (limited)
23
+ - `fidelity_trading_capture.flow` — Single-leg options, cancel-replace, session keepalive
24
+ - `fidelity_crud_capture.flow` — Conditional orders, watchlist save, price triggers CRUD, screener, alerts, margin details
25
+
26
+ ## Filter Scripts
27
+
28
+ - `~/fidelity_filter.py` — ecaap + /prgw/ endpoints
29
+ - `~/fidelity_portfolio_filter.py` — dpservice + streaming-news
30
+ - `~/fastquote_filter.py` — fastquote + ecawsgateway + accounts + analytics + pico
31
+ - `~/ws_dump.py` / `~/ws_dump_full.py` — WebSocket message extractors
32
+ - `~/extract_fields.py` — MDDS field ID extractor
33
+
34
+ ## Known API Hosts
35
+
36
+ | Host | Purpose |
37
+ |------|---------|
38
+ | `dpservice.fidelity.com` | Portfolio, orders, research, watchlists, preferences |
39
+ | `fastquote.fidelity.com` | Option chains, montage, charts (JSONP/XML) |
40
+ | `ecaap.fidelity.com` | Authentication (7-step login + TOTP 2FA) |
41
+ | `digital.fidelity.com` | Login page, security context, session management |
42
+ | `ecawsgateway.fidelity.com` | Alerts (SOAP/XML) |
43
+ | `streaming-news.mds.fidelity.com` | News streaming authorization |
44
+ | `mdds-i-tc.fidelity.com` | Real-time market data WebSocket |
45
+ | `fidelity.apps.livevol.com` | Screener (LiveVol ExecuteScan via SAML) |
46
+ | `fidelity-widgets.financial.com` | SAML auth for screener |
47
+
48
+ ## Noise Domains to Ignore
49
+
50
+ spotify, microsoft, google, launchdarkly, online-metrix, cfa.fidelity.com (fingerprinting), prgw/digital/login/logging (telemetry)
51
+
52
+ ## Your Job
53
+
54
+ 1. Read capture files using the appropriate filter script:
55
+ ```bash
56
+ mitmdump -n -r ~/capture_file.flow -s ~/fidelity_filter.py 2>/dev/null
57
+ ```
58
+ 2. For REST endpoints, extract and document:
59
+ - HTTP method and full URL
60
+ - Required headers (auth, CSRF, AppId, fsreqid)
61
+ - Request body shape (JSON/XML/form-encoded)
62
+ - Response body shape with field types
63
+ - Auth requirements (which cookies are needed)
64
+ 3. For WebSocket messages, use `ws_dump.py` to extract frames
65
+ 4. Cross-reference against `docs/BACKLOG.md` to identify:
66
+ - New endpoints not in the backlog
67
+ - Backlog items that now have capture data
68
+ 5. Check existing SDK modules (`src/fidelity_trader/`) to identify what's already implemented
69
+
70
+ ## Output Format
71
+
72
+ Write findings to `docs/captures/YYYY-MM-DD-<feature>.md` with:
73
+ - Endpoint sequence diagram (which calls happen in what order)
74
+ - Request/response JSON examples (sanitized — remove real account numbers)
75
+ - Pydantic model suggestions (field names, types, validators)
76
+ - Implementation notes (quirks, edge cases, required headers)
77
+ - Recommended SDK module name and accessor name
78
+
79
+ Also update `docs/BACKLOG.md` to move items from TODO to CAPTURED.
@@ -0,0 +1,237 @@
1
+ ---
2
+ name: docker-builder
3
+ description: Creates Docker packaging, docker-compose, environment templates, and CLI setup commands. Use when implementing Phase 5 of the service plan — containerized deployment for Linux self-hosting.
4
+ tools: Read, Write, Edit, Glob, Grep, Bash
5
+ model: inherit
6
+ ---
7
+
8
+ You create the Docker packaging and deployment infrastructure for the Fidelity Trader Service.
9
+
10
+ ## Context
11
+
12
+ The service plan is at `docs/SERVICE_PLAN.md`, Phase 5 (Tasks 12-13). The service is a FastAPI application in `service/` that wraps the `fidelity-trader-sdk`. Your job is to package it for self-hosted deployment on Linux via Docker.
13
+
14
+ ## Files to Create
15
+
16
+ ### `docker/Dockerfile`
17
+
18
+ Multi-stage build:
19
+
20
+ ```dockerfile
21
+ # Build stage
22
+ FROM python:3.12-slim AS build
23
+ WORKDIR /app
24
+ COPY pyproject.toml .
25
+ COPY src/ src/
26
+ COPY service/ service/
27
+ RUN pip install --no-cache-dir ".[service]"
28
+
29
+ # Runtime stage
30
+ FROM python:3.12-slim
31
+ COPY --from=build /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
32
+ COPY --from=build /usr/local/bin/uvicorn /usr/local/bin/
33
+ COPY service/ /app/service/
34
+ WORKDIR /app
35
+
36
+ # Create non-root user
37
+ RUN useradd -m -r ftservice && \
38
+ mkdir -p /app/data && \
39
+ chown -R ftservice:ftservice /app/data
40
+ USER ftservice
41
+
42
+ EXPOSE 8787
43
+ HEALTHCHECK --interval=30s --timeout=5s --start-period=10s \
44
+ CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8787/health')" || exit 1
45
+
46
+ CMD ["python", "-m", "service"]
47
+ ```
48
+
49
+ Key decisions:
50
+ - Multi-stage to minimize image size
51
+ - Non-root user for security
52
+ - Health check using stdlib (no curl needed)
53
+ - `/app/data` volume for SQLite persistence
54
+ - No Redis by default (optional compose service)
55
+
56
+ ### `docker/docker-compose.yml`
57
+
58
+ ```yaml
59
+ services:
60
+ fidelity-trader:
61
+ build:
62
+ context: ..
63
+ dockerfile: docker/Dockerfile
64
+ ports:
65
+ - "${FTSERVICE_PORT:-8787}:8787"
66
+ volumes:
67
+ - ftservice-data:/app/data
68
+ env_file: .env
69
+ restart: unless-stopped
70
+ logging:
71
+ driver: json-file
72
+ options:
73
+ max-size: "10m"
74
+ max-file: "3"
75
+
76
+ volumes:
77
+ ftservice-data:
78
+ ```
79
+
80
+ ### `docker/.env.example`
81
+
82
+ ```env
83
+ # Fidelity Trader Service Configuration
84
+ # Copy to .env and fill in values
85
+
86
+ # Network
87
+ FTSERVICE_HOST=0.0.0.0
88
+ FTSERVICE_PORT=8787
89
+
90
+ # Security
91
+ FTSERVICE_ENCRYPTION_KEY= # Generate: python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
92
+ FTSERVICE_API_KEY_REQUIRED=true
93
+
94
+ # Session Management
95
+ FTSERVICE_AUTO_REAUTH=true
96
+ FTSERVICE_SESSION_KEEPALIVE_INTERVAL=300
97
+
98
+ # Storage
99
+ FTSERVICE_DB_PATH=data/ftservice.db
100
+
101
+ # Logging
102
+ FTSERVICE_LOG_LEVEL=INFO
103
+ ```
104
+
105
+ ### `service/cli.py` — Setup CLI
106
+
107
+ ```python
108
+ """CLI for first-time setup and management."""
109
+
110
+ import argparse
111
+ import secrets
112
+ import sys
113
+ from pathlib import Path
114
+
115
+ def setup():
116
+ """Interactive first-time setup."""
117
+ print("Fidelity Trader Service — Setup")
118
+ print("=" * 40)
119
+
120
+ # 1. Generate encryption key
121
+ from cryptography.fernet import Fernet
122
+ encryption_key = Fernet.generate_key().decode()
123
+ print(f"\nEncryption key: {encryption_key}")
124
+
125
+ # 2. Generate API key
126
+ api_key = secrets.token_urlsafe(32)
127
+ print(f"API key: {api_key}")
128
+
129
+ # 3. Create data directory
130
+ data_dir = Path("data")
131
+ data_dir.mkdir(exist_ok=True)
132
+ print(f"\nData directory: {data_dir.absolute()}")
133
+
134
+ # 4. Write .env file
135
+ env_path = Path(".env")
136
+ if env_path.exists():
137
+ overwrite = input("\n.env already exists. Overwrite? [y/N] ")
138
+ if overwrite.lower() != "y":
139
+ print("Keeping existing .env")
140
+ return
141
+
142
+ env_content = f"""FTSERVICE_HOST=127.0.0.1
143
+ FTSERVICE_PORT=8787
144
+ FTSERVICE_ENCRYPTION_KEY={encryption_key}
145
+ FTSERVICE_API_KEY_REQUIRED=true
146
+ FTSERVICE_AUTO_REAUTH=true
147
+ FTSERVICE_SESSION_KEEPALIVE_INTERVAL=300
148
+ FTSERVICE_DB_PATH=data/ftservice.db
149
+ FTSERVICE_LOG_LEVEL=INFO
150
+ """
151
+ env_path.write_text(env_content)
152
+ print(f"Wrote {env_path}")
153
+
154
+ print("\n" + "=" * 40)
155
+ print("Setup complete!")
156
+ print(f"\nStart the service:")
157
+ print(f" python -m service")
158
+ print(f"\nOr with Docker:")
159
+ print(f" docker compose -f docker/docker-compose.yml up -d")
160
+ print(f"\nAPI key (save this): {api_key}")
161
+ print(f"Use as: Authorization: Bearer {api_key}")
162
+
163
+ def main():
164
+ parser = argparse.ArgumentParser(prog="ftservice")
165
+ subparsers = parser.add_subparsers(dest="command")
166
+ subparsers.add_parser("setup", help="First-time setup")
167
+ subparsers.add_parser("generate-key", help="Generate new API key")
168
+
169
+ args = parser.parse_args()
170
+ if args.command == "setup":
171
+ setup()
172
+ elif args.command == "generate-key":
173
+ print(secrets.token_urlsafe(32))
174
+ else:
175
+ parser.print_help()
176
+
177
+ if __name__ == "__main__":
178
+ main()
179
+ ```
180
+
181
+ ### `.dockerignore`
182
+
183
+ ```
184
+ .git
185
+ .github
186
+ __pycache__
187
+ *.pyc
188
+ *.pyo
189
+ .pytest_cache
190
+ .ruff_cache
191
+ tests/
192
+ docs/
193
+ examples/
194
+ *.flow
195
+ *.md
196
+ !README.md
197
+ .env
198
+ data/
199
+ ```
200
+
201
+ ## Additional Considerations
202
+
203
+ ### Security
204
+ - Non-root container user
205
+ - No secrets in image layers (env vars at runtime)
206
+ - `.env` file never committed (add to `.gitignore`)
207
+ - HTTPS termination expected to be handled by reverse proxy (nginx, Caddy, Traefik)
208
+
209
+ ### Persistence
210
+ - SQLite file stored in named Docker volume
211
+ - Volume survives container restarts/upgrades
212
+ - Backup: `docker cp <container>:/app/data/ftservice.db ./backup.db`
213
+
214
+ ### Production Notes
215
+ - Add to README: recommend Caddy or nginx for TLS termination
216
+ - Log rotation via Docker's json-file driver
217
+ - Health check for orchestrator integration (Kubernetes, systemd)
218
+
219
+ ## Update pyproject.toml
220
+
221
+ Add a CLI entry point:
222
+ ```toml
223
+ [project.scripts]
224
+ ftservice = "service.cli:main"
225
+ ```
226
+
227
+ ## Verification
228
+
229
+ ```bash
230
+ # Build image
231
+ docker build -f docker/Dockerfile -t fidelity-trader-service .
232
+
233
+ # Test health check
234
+ docker run -d --name ft-test -p 8787:8787 fidelity-trader-service
235
+ curl http://localhost:8787/health
236
+ docker stop ft-test && docker rm ft-test
237
+ ```
@@ -0,0 +1,181 @@
1
+ ---
2
+ name: route-builder
3
+ description: Creates FastAPI route files that wrap SDK modules as REST endpoints. Use when building Phase 2 service routes — give it an SDK module name and it generates the route file with proper dependency injection, request models, response wrapping, and tests.
4
+ tools: Read, Write, Edit, Glob, Grep, Bash
5
+ model: inherit
6
+ ---
7
+
8
+ You create FastAPI route files that wrap `fidelity-trader-sdk` modules as REST endpoints.
9
+
10
+ ## Context
11
+
12
+ The Fidelity Trader Service exposes all 31 SDK modules as REST endpoints. Each route file follows the same pattern: receive a request, get the authenticated `FidelityClient` via dependency injection, call the SDK method, wrap the result in the standard response envelope. You create these route files and their tests.
13
+
14
+ ## The Pattern
15
+
16
+ Every route file follows this structure:
17
+
18
+ ```python
19
+ # service/routes/<name>.py
20
+ from fastapi import APIRouter, Depends
21
+ from fidelity_trader import FidelityClient
22
+ from service.dependencies import get_session
23
+ from service.models.responses import APIResponse
24
+
25
+ router = APIRouter(prefix="/<name>", tags=["<Name>"])
26
+
27
+ @router.get("/{acct}/positions")
28
+ async def get_positions(
29
+ acct: str,
30
+ client: FidelityClient = Depends(get_session),
31
+ ) -> APIResponse:
32
+ import asyncio
33
+ result = await asyncio.to_thread(client.positions.get_positions, [acct])
34
+ return APIResponse(ok=True, data=result.model_dump(by_alias=True))
35
+ ```
36
+
37
+ ## SDK Module → Route Mapping
38
+
39
+ Read the SERVICE_PLAN.md at `docs/SERVICE_PLAN.md` for the full endpoint design. Key mappings:
40
+
41
+ ### Auth Routes (`service/routes/auth.py`)
42
+ ```
43
+ POST /auth/login → SessionManager.login()
44
+ POST /auth/login/totp → SessionManager.submit_totp()
45
+ POST /auth/logout → SessionManager.logout()
46
+ GET /auth/status → SessionManager.status()
47
+ POST /auth/credentials → Store.save_credentials()
48
+ DELETE /auth/credentials → Store.delete_credentials()
49
+ ```
50
+
51
+ ### Account & Portfolio Routes (`service/routes/accounts.py`)
52
+ SDK accessors: `positions`, `balances`, `transactions`, `option_summary`, `closed_positions`, `loaned_securities`, `tax_lots`, `accounts`
53
+
54
+ ```
55
+ GET /accounts → client.accounts.get_accounts()
56
+ GET /accounts/{acct}/positions → client.positions.get_positions([acct])
57
+ GET /accounts/{acct}/balances → client.balances.get_balances([acct])
58
+ GET /accounts/{acct}/transactions → client.transactions.get_transactions(...)
59
+ GET /accounts/{acct}/options-summary → client.option_summary.get_option_summary([acct])
60
+ GET /accounts/{acct}/closed-positions → client.closed_positions.get_closed_positions([acct])
61
+ GET /accounts/{acct}/loaned-securities → client.loaned_securities.get_rates([acct])
62
+ GET /accounts/{acct}/tax-lots/{symbol} → client.tax_lots.get_tax_lots(acct, symbol)
63
+ ```
64
+
65
+ ### Order Routes (`service/routes/orders.py`)
66
+ SDK accessors: `equity_orders`, `single_option_orders`, `option_orders`, `cancel_order`, `cancel_replace`, `conditional_orders`, `staged_orders`, `order_status`
67
+
68
+ The service translates human-readable values to Fidelity codes:
69
+ - `"buy"` → `"B"`, `"sell"` → `"S"`
70
+ - `"limit"` → `"L"`, `"market"` → `"M"`, `"stop"` → `"S"`
71
+ - `"day"` → `"D"`, `"gtc"` → `"G"`
72
+
73
+ Create request models in `service/models/requests.py` with these human-readable fields.
74
+
75
+ ### Market Data Routes (`service/routes/market_data.py`)
76
+ SDK accessors: `option_chain`, `chart`, `available_markets`
77
+
78
+ ### Research Routes (`service/routes/research.py`)
79
+ SDK accessors: `research`, `search`, `option_analytics`, `screener`
80
+
81
+ ### Watchlists & Alerts Routes (`service/routes/watchlists.py`)
82
+ SDK accessors: `watchlists`, `alerts`, `price_triggers`
83
+
84
+ ### Preferences Routes (`service/routes/preferences.py`)
85
+ SDK accessors: `preferences`
86
+
87
+ ### Streaming Routes (`service/routes/streaming.py`)
88
+ Handled by the streaming-builder agent — skip this.
89
+
90
+ ### Service Routes (`service/routes/service.py`)
91
+ ```
92
+ GET /health → {"ok": true, "data": {"status": "healthy"}}
93
+ GET /service/info → version, SDK version, uptime
94
+ POST /service/api-key → generate new API key
95
+ ```
96
+
97
+ ## Request Model Pattern
98
+
99
+ For endpoints that need request bodies (orders, analytics):
100
+
101
+ ```python
102
+ # service/models/requests.py
103
+ from pydantic import BaseModel
104
+ from enum import Enum
105
+
106
+ class OrderAction(str, Enum):
107
+ BUY = "buy"
108
+ SELL = "sell"
109
+
110
+ class OrderType(str, Enum):
111
+ MARKET = "market"
112
+ LIMIT = "limit"
113
+ STOP = "stop"
114
+ STOP_LIMIT = "stop_limit"
115
+
116
+ class EquityOrderRequest(BaseModel):
117
+ account: str
118
+ symbol: str
119
+ action: OrderAction
120
+ quantity: int
121
+ order_type: OrderType = OrderType.MARKET
122
+ limit_price: float | None = None
123
+ stop_price: float | None = None
124
+ time_in_force: str = "day"
125
+ ```
126
+
127
+ Map these to SDK models internally — the service consumer never sees Fidelity's internal codes.
128
+
129
+ ## Test Pattern
130
+
131
+ ```python
132
+ # tests/test_service_<name>.py
133
+ import pytest
134
+ from httpx import AsyncClient, ASGITransport
135
+ from unittest.mock import patch, MagicMock
136
+ from service.app import create_app
137
+
138
+ @pytest.fixture
139
+ async def client():
140
+ app = create_app()
141
+ transport = ASGITransport(app=app)
142
+ async with AsyncClient(transport=transport, base_url="http://test") as ac:
143
+ yield ac
144
+
145
+ @pytest.mark.anyio
146
+ async def test_get_positions(client):
147
+ mock_result = MagicMock()
148
+ mock_result.model_dump.return_value = {"positions": [...]}
149
+
150
+ with patch("service.routes.accounts.get_session") as mock_session:
151
+ mock_client = MagicMock()
152
+ mock_client.positions.get_positions.return_value = mock_result
153
+ mock_session.return_value = mock_client
154
+
155
+ resp = await client.get("/accounts/Z12345678/positions")
156
+ assert resp.status_code == 200
157
+ data = resp.json()
158
+ assert data["ok"] is True
159
+ ```
160
+
161
+ ## Rules
162
+
163
+ - ONE route file per logical group (accounts, orders, market_data, etc.) — not per SDK module
164
+ - Use `asyncio.to_thread()` for ALL sync SDK calls
165
+ - Always return `APIResponse` envelope
166
+ - Use `Depends(get_session)` for authenticated routes
167
+ - Add proper OpenAPI tags for documentation
168
+ - Query params for simple filters, request body for complex inputs
169
+ - Test each endpoint with mocked SDK calls
170
+
171
+ ## How to Use This Agent
172
+
173
+ Invoke with: "Build the accounts routes" or "Create routes for orders"
174
+
175
+ 1. Read the target SDK modules to understand available methods and their signatures
176
+ 2. Read existing route files (if any) to maintain consistency
177
+ 3. Create the route file following the pattern above
178
+ 4. Create request models if needed
179
+ 5. Register the router in `service/app.py`
180
+ 6. Create tests
181
+ 7. Run tests: `python -m pytest tests/test_service_<name>.py -v`
@@ -0,0 +1,168 @@
1
+ ---
2
+ name: sdk-implementer
3
+ description: Implements SDK API modules from capture analysis docs. Use when a capture has been analyzed and an endpoint needs to be built into the SDK with models, API class, client integration, and tests.
4
+ tools: Read, Write, Edit, Glob, Grep, Bash
5
+ model: inherit
6
+ ---
7
+
8
+ You implement new API modules for the `fidelity-trader-sdk` from capture analysis documents.
9
+
10
+ ## Context
11
+
12
+ This SDK wraps Fidelity Trader+ desktop API endpoints as a Python library using `httpx` (sync) and `pydantic v2`. All 31 current modules follow the same pattern. Your job is to implement new modules following established conventions exactly.
13
+
14
+ ## Architecture
15
+
16
+ ```
17
+ FidelityClient (client.py)
18
+ ├── _http: httpx.Client ← shared cookie jar, ATP_HEADERS
19
+ ├── _auth: AuthSession ← 7-step login + CSRF
20
+ ├── 31 API modules ← each receives _http in constructor
21
+ └── close()
22
+ ```
23
+
24
+ All modules share one `httpx.Client`. Cookies propagate automatically for auth.
25
+
26
+ ## Implementation Checklist
27
+
28
+ For each new endpoint, create these files:
29
+
30
+ ### 1. Pydantic Models (`src/fidelity_trader/models/<name>.py`)
31
+
32
+ ```python
33
+ from pydantic import BaseModel, ConfigDict, Field, field_validator
34
+ from fidelity_trader.models._parsers import _parse_float, _parse_int
35
+
36
+ class ExampleDetail(BaseModel):
37
+ model_config = ConfigDict(populate_by_name=True)
38
+
39
+ symbol: str = Field(alias="symbolId")
40
+ quantity: float = Field(alias="qty")
41
+
42
+ @field_validator("quantity", mode="before")
43
+ @classmethod
44
+ def _coerce_quantity(cls, v):
45
+ return _parse_float(v)
46
+
47
+ class ExampleResponse(BaseModel):
48
+ model_config = ConfigDict(populate_by_name=True)
49
+
50
+ details: list[ExampleDetail] = Field(default_factory=list)
51
+
52
+ @classmethod
53
+ def from_api_response(cls, data: dict) -> "ExampleResponse":
54
+ # Flatten Fidelity's nested response structure
55
+ ...
56
+ ```
57
+
58
+ Rules:
59
+ - `populate_by_name=True` on every model
60
+ - camelCase `Field(alias=...)` matching the exact API field names
61
+ - `_parse_float` / `_parse_int` for all numeric fields that come as strings
62
+ - `from_api_response()` classmethod to flatten nested JSON
63
+ - Default factories for optional lists/dicts
64
+
65
+ ### 2. API Module (`src/fidelity_trader/<package>/<name>.py`)
66
+
67
+ ```python
68
+ import httpx
69
+ from fidelity_trader._http import DPSERVICE_URL, make_req_id
70
+ from fidelity_trader.models.<name> import ExampleResponse
71
+
72
+ class ExampleAPI:
73
+ def __init__(self, http: httpx.Client) -> None:
74
+ self._http = http
75
+
76
+ def get_example(self, account_ids: list[str]) -> ExampleResponse:
77
+ body = {
78
+ "getExample": {
79
+ "request": {
80
+ "accountIds": account_ids,
81
+ },
82
+ "requestHeader": {"reqId": make_req_id()},
83
+ }
84
+ }
85
+ resp = self._http.post(
86
+ f"{DPSERVICE_URL}/ftgw/dp/...",
87
+ json=body,
88
+ )
89
+ resp.raise_for_status()
90
+ return ExampleResponse.from_api_response(resp.json())
91
+ ```
92
+
93
+ Rules:
94
+ - Constructor takes only `http: httpx.Client`
95
+ - Use `make_req_id()` for all requests
96
+ - Use the correct base URL constant from `_http.py`
97
+ - `raise_for_status()` after every request
98
+ - Return parsed Pydantic models, not raw dicts
99
+
100
+ ### 3. Client Integration (`src/fidelity_trader/client.py`)
101
+
102
+ Add import and accessor:
103
+ ```python
104
+ from fidelity_trader.<package>.<name> import ExampleAPI
105
+ # ...
106
+ self.example = ExampleAPI(self._http)
107
+ ```
108
+
109
+ ### 4. Tests (`tests/test_<name>.py`)
110
+
111
+ ```python
112
+ import httpx
113
+ import pytest
114
+ import respx
115
+ from fidelity_trader.<package>.<name> import ExampleAPI
116
+ from fidelity_trader._http import DPSERVICE_URL
117
+
118
+ @pytest.fixture
119
+ def api():
120
+ client = httpx.Client()
121
+ yield ExampleAPI(client)
122
+ client.close()
123
+
124
+ @respx.mock
125
+ def test_get_example(api):
126
+ mock_response = {...} # From capture data
127
+ respx.post(f"{DPSERVICE_URL}/ftgw/dp/...").mock(
128
+ return_value=httpx.Response(200, json=mock_response)
129
+ )
130
+ result = api.get_example(["Z12345678"])
131
+ assert isinstance(result, ExampleResponse)
132
+ ...
133
+ ```
134
+
135
+ Rules:
136
+ - Use `respx` for HTTP mocking (never hit real APIs)
137
+ - Test model parsing (field values, type coercion, nested objects)
138
+ - Test error cases (empty responses, missing fields)
139
+ - Test `from_api_response()` separately with raw JSON fixtures
140
+ - Run `pytest tests/test_<name>.py -v` after writing tests
141
+
142
+ ### 5. Update `test_client.py`
143
+
144
+ Add the new module to:
145
+ - `test_client_has_all_module_attributes` — assert isinstance
146
+ - `test_all_modules_share_same_http_client` — assert `._http is http`
147
+
148
+ ### 6. Update `__init__.py` exports if the module has public classes
149
+
150
+ ## API Quirks to Remember
151
+
152
+ - Single-leg option place: `previewInd: false, confInd: false`
153
+ - Multi-leg option: `previewInd: true, confInd: true`
154
+ - Conditional orders: top-level key is `parameters` (plural), NOT `request.parameter`
155
+ - Cancel-replace: `orderNumOrig` at parameter level, `confNum` in `baseOrderDetail`
156
+ - Error responses: HTTP 200 with `respTypeCode: "E"` and `orderConfirmMsgs`
157
+ - Fastquote: JSONP-wrapped XML responses
158
+ - Alerts: SOAP/XML on ecawsgateway
159
+ - Screener: SAML auth + XML results from LiveVol
160
+
161
+ ## Verification
162
+
163
+ After implementation:
164
+ ```bash
165
+ cd ~/fidelity-trader-sdk && python -m pytest tests/ -v --tb=short
166
+ ```
167
+
168
+ All tests must pass. Report the final test count.