okama-planner 0.4.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 (117) hide show
  1. okama_planner-0.4.0/LICENSE +21 -0
  2. okama_planner-0.4.0/PKG-INFO +280 -0
  3. okama_planner-0.4.0/README.md +252 -0
  4. okama_planner-0.4.0/docs/charts.md +118 -0
  5. okama_planner-0.4.0/docs/contract.md +79 -0
  6. okama_planner-0.4.0/docs/images/README.md +33 -0
  7. okama_planner-0.4.0/docs/images/financial-plan-three-goals.png +0 -0
  8. okama_planner-0.4.0/docs/joint-scenarios.md +66 -0
  9. okama_planner-0.4.0/docs/portfolio-modes.md +272 -0
  10. okama_planner-0.4.0/docs/releases/v0.4.0.md +59 -0
  11. okama_planner-0.4.0/docs/reports.md +208 -0
  12. okama_planner-0.4.0/docs/retirement-utility.md +137 -0
  13. okama_planner-0.4.0/docs/storage.md +161 -0
  14. okama_planner-0.4.0/examples/baseline-request.json +316 -0
  15. okama_planner-0.4.0/examples/baseline-result.json +3288 -0
  16. okama_planner-0.4.0/examples/charts.py +28 -0
  17. okama_planner-0.4.0/examples/collect_currency_assumptions.py +76 -0
  18. okama_planner-0.4.0/examples/currency-assumptions.json +1221 -0
  19. okama_planner-0.4.0/examples/deferred-request.json +316 -0
  20. okama_planner-0.4.0/examples/deferred-result.json +3288 -0
  21. okama_planner-0.4.0/examples/demo.py +30 -0
  22. okama_planner-0.4.0/examples/family-per-goal-request.json +356 -0
  23. okama_planner-0.4.0/examples/family-per-goal-result.json +9993 -0
  24. okama_planner-0.4.0/examples/family-single-request.json +406 -0
  25. okama_planner-0.4.0/examples/family-single-result.json +10011 -0
  26. okama_planner-0.4.0/examples/family.json +316 -0
  27. okama_planner-0.4.0/examples/multilingual_reports.py +253 -0
  28. okama_planner-0.4.0/examples/portfolio_modes.py +117 -0
  29. okama_planner-0.4.0/examples/readme-metadata.json +328 -0
  30. okama_planner-0.4.0/examples/readme-request.json +384 -0
  31. okama_planner-0.4.0/examples/readme-result.json +25819 -0
  32. okama_planner-0.4.0/examples/reports.py +42 -0
  33. okama_planner-0.4.0/examples/request-schema.json +1040 -0
  34. okama_planner-0.4.0/examples/versions.json +7 -0
  35. okama_planner-0.4.0/extraction-manifest.json +124 -0
  36. okama_planner-0.4.0/pyproject.toml +51 -0
  37. okama_planner-0.4.0/src/okama_planner/__init__.py +33 -0
  38. okama_planner-0.4.0/src/okama_planner/_chart_assets/ECHARTS-LICENSE.txt +222 -0
  39. okama_planner-0.4.0/src/okama_planner/_chart_assets/ECHARTS-NOTICE.txt +5 -0
  40. okama_planner-0.4.0/src/okama_planner/_chart_assets/LICENSE-d3.txt +27 -0
  41. okama_planner-0.4.0/src/okama_planner/_chart_assets/README.md +21 -0
  42. okama_planner-0.4.0/src/okama_planner/_chart_assets/charts.js +201 -0
  43. okama_planner-0.4.0/src/okama_planner/_chart_assets/echarts.min.js +45 -0
  44. okama_planner-0.4.0/src/okama_planner/_chart_assets/page.html +60 -0
  45. okama_planner-0.4.0/src/okama_planner/allocation.py +200 -0
  46. okama_planner-0.4.0/src/okama_planner/api.py +391 -0
  47. okama_planner-0.4.0/src/okama_planner/asset_classes.py +11 -0
  48. okama_planner-0.4.0/src/okama_planner/charts.py +237 -0
  49. okama_planner-0.4.0/src/okama_planner/forecast/__init__.py +1 -0
  50. okama_planner-0.4.0/src/okama_planner/forecast/distributions.py +44 -0
  51. okama_planner-0.4.0/src/okama_planner/forecast/goal_results.py +145 -0
  52. okama_planner-0.4.0/src/okama_planner/forecast/plan.py +180 -0
  53. okama_planner-0.4.0/src/okama_planner/forecast/portfolios.py +99 -0
  54. okama_planner-0.4.0/src/okama_planner/forecast/results.py +36 -0
  55. okama_planner-0.4.0/src/okama_planner/forecast/variants.py +60 -0
  56. okama_planner-0.4.0/src/okama_planner/history.py +38 -0
  57. okama_planner-0.4.0/src/okama_planner/horizon.py +53 -0
  58. okama_planner-0.4.0/src/okama_planner/inputs.py +163 -0
  59. okama_planner-0.4.0/src/okama_planner/ledger/__init__.py +1 -0
  60. okama_planner-0.4.0/src/okama_planner/ledger/budget.py +64 -0
  61. okama_planner-0.4.0/src/okama_planner/ledger/buffer.py +153 -0
  62. okama_planner-0.4.0/src/okama_planner/ledger/build.py +358 -0
  63. okama_planner-0.4.0/src/okama_planner/ledger/calendar.py +48 -0
  64. okama_planner-0.4.0/src/okama_planner/ledger/goal_savings.py +176 -0
  65. okama_planner-0.4.0/src/okama_planner/ledger/goals.py +228 -0
  66. okama_planner-0.4.0/src/okama_planner/ledger/indexation.py +17 -0
  67. okama_planner-0.4.0/src/okama_planner/ledger/mortgage.py +126 -0
  68. okama_planner-0.4.0/src/okama_planner/ledger/types.py +92 -0
  69. okama_planner-0.4.0/src/okama_planner/localization.py +23 -0
  70. okama_planner-0.4.0/src/okama_planner/rates.py +46 -0
  71. okama_planner-0.4.0/src/okama_planner/reports.py +978 -0
  72. okama_planner-0.4.0/src/okama_planner/scenarios.py +108 -0
  73. okama_planner-0.4.0/src/okama_planner/segmented.py +685 -0
  74. okama_planner-0.4.0/src/okama_planner/storage/__init__.py +6 -0
  75. okama_planner-0.4.0/src/okama_planner/storage/database.py +153 -0
  76. okama_planner-0.4.0/src/okama_planner/storage/migrations/env.py +8 -0
  77. okama_planner-0.4.0/src/okama_planner/storage/migrations/versions/0001_registry.py +42 -0
  78. okama_planner-0.4.0/src/okama_planner/storage/migrations/versions/0002_plans.py +57 -0
  79. okama_planner-0.4.0/src/okama_planner/storage/models.py +117 -0
  80. okama_planner-0.4.0/src/okama_planner/storage/plans.py +167 -0
  81. okama_planner-0.4.0/src/okama_planner/storage/registry.py +105 -0
  82. okama_planner-0.4.0/src/okama_planner/storage/template.py +10 -0
  83. okama_planner-0.4.0/src/okama_planner/storage/templates/empty.sqlite3 +0 -0
  84. okama_planner-0.4.0/src/okama_planner/storage/validation.py +81 -0
  85. okama_planner-0.4.0/src/okama_planner/terminology.csv +205 -0
  86. okama_planner-0.4.0/src/okama_planner/utility.py +304 -0
  87. okama_planner-0.4.0/tests/browser/check_chart_options.cjs +108 -0
  88. okama_planner-0.4.0/tests/browser/check_charts.cjs +183 -0
  89. okama_planner-0.4.0/tests/planner_tests/__init__.py +0 -0
  90. okama_planner-0.4.0/tests/planner_tests/forecast/__init__.py +0 -0
  91. okama_planner-0.4.0/tests/planner_tests/forecast/test_distributions.py +48 -0
  92. okama_planner-0.4.0/tests/planner_tests/forecast/test_goal_results.py +271 -0
  93. okama_planner-0.4.0/tests/planner_tests/forecast/test_results.py +69 -0
  94. okama_planner-0.4.0/tests/planner_tests/ledger/__init__.py +0 -0
  95. okama_planner-0.4.0/tests/planner_tests/ledger/test_budget.py +155 -0
  96. okama_planner-0.4.0/tests/planner_tests/ledger/test_buffer.py +216 -0
  97. okama_planner-0.4.0/tests/planner_tests/ledger/test_build.py +1132 -0
  98. okama_planner-0.4.0/tests/planner_tests/ledger/test_calendar.py +51 -0
  99. okama_planner-0.4.0/tests/planner_tests/ledger/test_goal_savings.py +194 -0
  100. okama_planner-0.4.0/tests/planner_tests/ledger/test_goals.py +413 -0
  101. okama_planner-0.4.0/tests/planner_tests/ledger/test_indexation.py +31 -0
  102. okama_planner-0.4.0/tests/planner_tests/ledger/test_mortgage.py +206 -0
  103. okama_planner-0.4.0/tests/storage/test_database.py +176 -0
  104. okama_planner-0.4.0/tests/storage/test_plans.py +151 -0
  105. okama_planner-0.4.0/tests/storage/test_registry.py +105 -0
  106. okama_planner-0.4.0/tests/storage/test_template.py +32 -0
  107. okama_planner-0.4.0/tests/test_allocation.py +275 -0
  108. okama_planner-0.4.0/tests/test_api.py +121 -0
  109. okama_planner-0.4.0/tests/test_charts.py +326 -0
  110. okama_planner-0.4.0/tests/test_currency_examples.py +148 -0
  111. okama_planner-0.4.0/tests/test_forecast.py +217 -0
  112. okama_planner-0.4.0/tests/test_portfolio_modes.py +197 -0
  113. okama_planner-0.4.0/tests/test_portfolio_modes_example.py +46 -0
  114. okama_planner-0.4.0/tests/test_reports.py +549 -0
  115. okama_planner-0.4.0/tests/test_scenarios.py +159 -0
  116. okama_planner-0.4.0/tests/test_segmented.py +328 -0
  117. okama_planner-0.4.0/tests/test_utility.py +356 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sergey Kikevich
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,280 @@
1
+ Metadata-Version: 2.4
2
+ Name: okama-planner
3
+ Version: 0.4.0
4
+ Summary: Personal and family financial planning powered by okama
5
+ License: MIT
6
+ License-File: LICENSE
7
+ Author: Sergey Kikevich
8
+ Requires-Python: >=3.11,<4.0
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.14
15
+ Classifier: Programming Language :: Python :: 3.15
16
+ Provides-Extra: reports
17
+ Requires-Dist: alembic (>=1.13,<2)
18
+ Requires-Dist: okama (>=3.0.0)
19
+ Requires-Dist: openpyxl (>=3.1,<4) ; extra == "reports"
20
+ Requires-Dist: pandas (>=2.0)
21
+ Requires-Dist: pillow (>=10) ; extra == "reports"
22
+ Requires-Dist: pydantic (>=2.0)
23
+ Requires-Dist: scipy (>=1.0)
24
+ Requires-Dist: sqlalchemy (>=2.0,<3)
25
+ Project-URL: Repository, https://github.com/mbk-dev/okama-planner
26
+ Description-Content-Type: text/markdown
27
+
28
+ <div align="center">
29
+
30
+ # okama Planner
31
+
32
+ **Open-source personal and family financial planning powered by okama.**
33
+
34
+ [![CI](https://github.com/mbk-dev/okama-planner/actions/workflows/ci.yml/badge.svg)](https://github.com/mbk-dev/okama-planner/actions/workflows/ci.yml) [![Python](https://img.shields.io/badge/Python-3.11%2B-blue)](pyproject.toml) [![MIT](https://img.shields.io/badge/License-MIT-green)](LICENSE)
35
+
36
+ [Quick start](#quick-start) · [Reports & charts](#reports--charts) · [MCP](#use-with-an-ai-assistant) · [Client records](#client-records) · [Languages](#languages)
37
+
38
+ </div>
39
+
40
+ ![Synthetic financial plan with three goals, a logarithmic USD axis, median and Monte Carlo percentile bands](docs/images/financial-plan-three-goals.png)
41
+
42
+ *Three goals, one household: **1 Car** (October 2029), **2 Home purchase** (October 2031),
43
+ **3 Early retirement** (October 2040). Forecast in USD through 2070, on a logarithmic scale;
44
+ blue median, shaded p25–p75 and p10–p90 ranges. Household inputs are fictional; returns use
45
+ frozen historical observations. Zero and negative values are not shown on a log axis.*
46
+
47
+ Build a monthly household plan, explore uncertainty, compare alternatives and export results
48
+ under your own brand. Designed for financial planners, technically comfortable individuals and
49
+ integration developers. Calculation quality comes first; Excel, charts and MCP provide ways to
50
+ use the application while a future web interface is explored.
51
+
52
+ ## What you can do
53
+
54
+ | Task | Available today |
55
+ |---|---|
56
+ | Model a household | Income, expenses, assets, fixed-payment loans, reserves and dated goals |
57
+ | Choose a portfolio approach | One pooled portfolio or explicitly allocated portfolios for each goal |
58
+ | Compare plans | Shared market scenarios, goal funding, unmet payments and portfolio/capital outcomes |
59
+ | Present results | Configurable Excel reports and interactive offline HTML charts |
60
+ | Share visuals | PNG and SVG charts, goal markers and independent logarithmic scales |
61
+ | Automate calculations | Python API and optional tools in the existing okama-mcp server |
62
+ | Keep client history | Local SQLite registry, versioned plans, scenarios and saved results |
63
+
64
+ Separate goal portfolios share synchronized market scenarios. Fixed-rate savings accounts are
65
+ also supported, but are a different concept from investment portfolios for goals.
66
+ See [portfolio modes](docs/portfolio-modes.md) for allocation, transfers and funding rules.
67
+
68
+ ## Quick start
69
+
70
+ Use **Python 3.11+** and [Poetry](https://python-poetry.org/). From a local source checkout:
71
+
72
+ ```bash
73
+ git clone https://github.com/mbk-dev/okama-planner.git
74
+ cd okama-planner
75
+ poetry env use python3.11
76
+ poetry install --extras reports
77
+ poetry run python examples/demo.py
78
+ poetry run python examples/portfolio_modes.py
79
+ ```
80
+
81
+ The first example compares a purchase now versus a deferred purchase. The second compares a
82
+ pooled portfolio with home and retirement portfolios on the same synthetic market scenarios.
83
+ Requests, results and an Excel comparison are saved under `tmp/`; neither example downloads
84
+ market data or needs a client database.
85
+
86
+ **Prefer to browse first?** Open the [saved family inputs](examples/family-single-request.json),
87
+ [results](examples/family-single-result.json) and [Excel report examples](https://github.com/mbk-dev/okama-planner/releases/tag/v0.4.0).
88
+ The [three-goal hero input](examples/readme-request.json) and [result](examples/readme-result.json)
89
+ are included with [dated assumptions and validation metadata](examples/readme-metadata.json).
90
+ The USD example uses 5,000 Monte Carlo paths; its independent validation estimates plan success
91
+ at 95.92% under the supplied assumptions. For exact numerical replay, use the versions in [examples/versions.json](examples/versions.json);
92
+ a seed alone does not freeze data or dependencies. [Calculation contract →](docs/contract.md)
93
+
94
+ ### Use the Python API
95
+
96
+ ```python
97
+ import json
98
+ from pathlib import Path
99
+ from okama_planner import forecast
100
+
101
+ request = json.loads(Path("examples/readme-request.json").read_text())
102
+ result = forecast(request)
103
+ ```
104
+
105
+ The result is a JSON-compatible dictionary containing cash flows, goals, forecast metrics,
106
+ chart series and provenance. Complete input validation uses `ForecastRequest`; its JSON Schema
107
+ is available through `ForecastRequest.model_json_schema()`.
108
+
109
+ ## Reports & charts
110
+
111
+ ### Excel under your own brand
112
+
113
+ Set your company name, contacts, logo and accent color. The exporter creates a new workbook;
114
+ it does not require a private template or a pre-existing client file.
115
+
116
+ ```python
117
+ from okama_planner.reports import ReportBrand, export_report
118
+
119
+ export_report(
120
+ [{"label": "Family plan", "request": request, "result": result}],
121
+ "family-plan.xlsx",
122
+ brand=ReportBrand(company="Example Advisory", color="244C66"),
123
+ language="en", # en, ru, zh, de, es
124
+ )
125
+ ```
126
+
127
+ | Workbook sections | What they show |
128
+ |---|---|
129
+ | Summary, Budget, Balance | Plan outcomes, planned monthly cash flows, portfolio and net capital |
130
+ | Goals, Assumptions, Comparison | Goal funding, model inputs and differences between scenarios |
131
+ | Ledger | Detailed planned cash-flow requirements |
132
+ | Segments, Allocation, Segment balances | Portfolio assignments, strategies and account projections |
133
+ | Funding events, Transfers | Actual funded/unmet payments and transfers in joint portfolio modes |
134
+ | Branding, Instructions | Your presentation settings and guidance for reading the workbook |
135
+
136
+ The optional sheets reflect the result schema and portfolio mode. Excel presents saved forecast
137
+ results: editing a cell does not rerun Monte Carlo. Change the input, recalculate and export again.
138
+ [Report details and fictional-brand examples →](docs/reports.md)
139
+
140
+ ### Interactive and shareable charts
141
+
142
+ ```python
143
+ from okama_planner.charts import export_charts
144
+
145
+ export_charts(result, "charts") # offline interactive HTML
146
+ export_charts(result, "charts/png", format="png")
147
+ export_charts(result, "charts/svg", format="svg")
148
+ ```
149
+
150
+ Portfolio and net capital are separate charts. HTML includes hover values, goal markers,
151
+ logarithmic-scale controls and image download buttons. Direct PNG/SVG rendering requires
152
+ Chrome or Chromium; HTML generation does not. This is a **chart export**, not a complete
153
+ HTML financial-plan report or a hosted web application. [Chart options →](docs/charts.md)
154
+
155
+ ## Use with an AI assistant
156
+
157
+ Install Planner into the same environment as the existing **okama-mcp** server. Its current
158
+ source branch exposes `planner_forecast` and `planner_compare_modes`, while preserving the
159
+ existing portfolio tools. The adapter calls Planner rather than duplicating its calculations.
160
+
161
+ [Local installation, client setup and worked MCP examples →](https://github.com/mbk-dev/okama-mcp/blob/main/docs/planner.md)
162
+
163
+ Planner reports, chart rendering and consumption-utility helpers are not yet exposed through
164
+ these MCP tools. The published MCP package and public HTTP server have not been updated for
165
+ this integration; use the source installation described in the linked guide.
166
+
167
+ ## Client records
168
+
169
+ **Designed for professional client work by financial advisors and financial planners.**
170
+ The local SQLite registry brings client identity, contacts, broker relationships and
171
+ planning history together: one stable client record is linked to multiple versions of
172
+ financial inputs, scenarios and saved calculations. It supports ongoing work with a client,
173
+ from collecting information and choosing how to communicate to revisiting their financial plan.
174
+
175
+ **Status: implemented in the Python API.** `okama_planner.storage` provides client
176
+ creation, reading and updates, financial versions, scenarios and saved forecast results.
177
+ The shipped SQLite template contains schema and zero client records, plans or results.
178
+ Access to this registry through okama-mcp is a separate planned integration.
179
+
180
+ ```python
181
+ from pathlib import Path
182
+ from okama_planner.storage import PlannerStore
183
+
184
+ path = Path.home() / "planner-data" / "clients.sqlite3"
185
+ path.parent.mkdir(parents=True, exist_ok=True)
186
+ with PlannerStore.initialize(path) as store:
187
+ assert store.list_clients() == []
188
+ ```
189
+
190
+ `initialize` refuses to overwrite a file; `PlannerStore.open(path)` reopens an existing
191
+ database. [Storage API, versioned snapshots and migrations →](docs/storage.md)
192
+
193
+ ### Complete client record
194
+
195
+ The table below shows **all 16 columns of Planner's `client_registry`**, with three entirely
196
+ fictional records. Fields run down the table so the complete record remains readable.
197
+ These examples exist **only in this README**, not in a bundled database or a seed script.
198
+ They illustrate the registry supported by the storage API.
199
+
200
+ | Field | Alex Morgan | Priya Rao | Jordan Lee |
201
+ |---|---|---|---|
202
+ | `id` — internal identifier | 1 | 2 | 3 |
203
+ | `code` — stable client code | c-0001 | c-0002 | c-0003 |
204
+ | `full_name` — full name | Alex Morgan | Priya Rao | Jordan Lee |
205
+ | `sex` — recorded sex | male | female | — |
206
+ | `birth_year` — year of birth | 1985 | 1990 | 1978 |
207
+ | `email` — email address | alex@example.invalid | priya@example.invalid | jordan@example.invalid |
208
+ | `phone` — telephone | — | — | — |
209
+ | `telegram` — Telegram handle | — | — | — |
210
+ | `telegram_id` — stable numeric Telegram ID | — | — | — |
211
+ | `whatsapp` — WhatsApp contact | — | — | — |
212
+ | `max_messenger` — MAX messenger contact | — | — | — |
213
+ | `brokers` — ordered broker list | ["Example Broker A"] | [] | — |
214
+ | `primary_channel` — main communication channel | email | email | email |
215
+ | `ips_sent_at` — date the investment policy statement was sent | 2026-09-15 | — | 2026-10-01 |
216
+ | `note` — advisor's working notes | Annual plan review | First planning meeting | Retirement scenarios |
217
+ | `created_at` — record creation timestamp (UTC) | 2026-09-01T09:00:00Z | 2026-09-08T10:00:00Z | 2026-09-20T08:30:00Z |
218
+
219
+ A dash means the value has not been recorded. For `brokers`, an empty list means the client
220
+ explicitly has no broker; a missing value means this is unknown. `primary_channel` points to
221
+ a contact that has been filled in. `telegram_id` preserves identity when a handle changes.
222
+ `ips_sent_at` records delivery of the investment policy statement, not automatic document creation.
223
+
224
+ ### Identity, versions and planning history
225
+
226
+ The database separates the person from their changing financial information:
227
+
228
+ | Related table | All columns | Role in the advisor's workflow |
229
+ |---|---|---|
230
+ | `client` | `id`, `registry_id`, `version`, `source_digest`, `note`, `created_at` | A version of the client's financial inputs; linked by `registry_id`, with a source fingerprint |
231
+ | `tax_residency` | `id`, `registry_id`, `year`, `country`, `note` | Tax-residence country by calendar year, using an ISO two-letter country code |
232
+
233
+ Family members, assets, liabilities, budget items, goals, portfolios and scenarios belong to
234
+ versions of client financial data in Planner. Saved calculation runs hold the input snapshot and model settings.
235
+ This structure lets an advisor keep earlier inputs and compare later plans without treating
236
+ an updated financial situation as a different person. Recording tax residency does not itself
237
+ calculate jurisdiction-specific taxes.
238
+
239
+ Each advisor keeps their actual database outside the public repository. MCP access to the
240
+ registry remains planned; the storage API is implemented. Private advisory documents and internal
241
+ skills are not part of the public package.
242
+
243
+ ## Languages
244
+
245
+ **Available today:** Excel reports and chart interface text in **English, Russian,
246
+ German, Spanish and Simplified Chinese** (`en`, `ru`, `de`, `es`, `zh`). Select a language
247
+ with `export_report(..., language="ru")` or `export_charts(..., language="ru")`.
248
+ The shared [terminology table](src/okama_planner/terminology.csv) supplies translated captions.
249
+ See the [five-language report example](examples/multilingual_reports.py).
250
+
251
+ The broader localization roadmap covers:
252
+
253
+ - Excel and future HTML/PDF report headings, sheet names, instructions and template text.
254
+ - Chart titles, controls, annotations and number, currency and date formatting.
255
+ - Client-registry field labels, descriptions, forms and user-facing views.
256
+ - Validation messages, tool descriptions shown by MCP clients, guides and demonstration materials.
257
+ - Future web interface labels and help text.
258
+
259
+ SQL column names, JSON keys and API identifiers will remain stable across languages.
260
+ Client names and other user-entered text are not automatically translated. Localized wording
261
+ does not imply support for a country's tax or pension rules. Additional languages and localization beyond the implemented
262
+ Excel/chart captions are roadmap items until their implementation is published.
263
+
264
+ ## Model boundaries & next steps
265
+
266
+ The current model does not perform FX conversion or implement jurisdiction-specific taxes or
267
+ transaction fees. Inputs must already reflect externally modelled taxes and fees.
268
+ Monte Carlo probabilities describe the supplied model and assumptions, not guaranteed outcomes.
269
+
270
+ Retirement consumption **CE, gamma and equivalent-alpha helpers** exist as a separate module;
271
+ they are not yet integrated into forecasts, MCP or reports.
272
+ [Method and applicability →](docs/retirement-utility.md)
273
+
274
+ Next steps include registry access through MCP, broader MCP exports and multilingual presentation.
275
+ A web interface is a later direction. The standalone package contains no private client data,
276
+ MBK documents, internal skills or dependency on the closed lfp application.
277
+
278
+ Explore the family: [okama library](https://github.com/mbk-dev/okama) ·
279
+ [okama.io](https://okama.io/) · [okama-mcp](https://github.com/mbk-dev/okama-mcp).
280
+
@@ -0,0 +1,252 @@
1
+ <div align="center">
2
+
3
+ # okama Planner
4
+
5
+ **Open-source personal and family financial planning powered by okama.**
6
+
7
+ [![CI](https://github.com/mbk-dev/okama-planner/actions/workflows/ci.yml/badge.svg)](https://github.com/mbk-dev/okama-planner/actions/workflows/ci.yml) [![Python](https://img.shields.io/badge/Python-3.11%2B-blue)](pyproject.toml) [![MIT](https://img.shields.io/badge/License-MIT-green)](LICENSE)
8
+
9
+ [Quick start](#quick-start) · [Reports & charts](#reports--charts) · [MCP](#use-with-an-ai-assistant) · [Client records](#client-records) · [Languages](#languages)
10
+
11
+ </div>
12
+
13
+ ![Synthetic financial plan with three goals, a logarithmic USD axis, median and Monte Carlo percentile bands](docs/images/financial-plan-three-goals.png)
14
+
15
+ *Three goals, one household: **1 Car** (October 2029), **2 Home purchase** (October 2031),
16
+ **3 Early retirement** (October 2040). Forecast in USD through 2070, on a logarithmic scale;
17
+ blue median, shaded p25–p75 and p10–p90 ranges. Household inputs are fictional; returns use
18
+ frozen historical observations. Zero and negative values are not shown on a log axis.*
19
+
20
+ Build a monthly household plan, explore uncertainty, compare alternatives and export results
21
+ under your own brand. Designed for financial planners, technically comfortable individuals and
22
+ integration developers. Calculation quality comes first; Excel, charts and MCP provide ways to
23
+ use the application while a future web interface is explored.
24
+
25
+ ## What you can do
26
+
27
+ | Task | Available today |
28
+ |---|---|
29
+ | Model a household | Income, expenses, assets, fixed-payment loans, reserves and dated goals |
30
+ | Choose a portfolio approach | One pooled portfolio or explicitly allocated portfolios for each goal |
31
+ | Compare plans | Shared market scenarios, goal funding, unmet payments and portfolio/capital outcomes |
32
+ | Present results | Configurable Excel reports and interactive offline HTML charts |
33
+ | Share visuals | PNG and SVG charts, goal markers and independent logarithmic scales |
34
+ | Automate calculations | Python API and optional tools in the existing okama-mcp server |
35
+ | Keep client history | Local SQLite registry, versioned plans, scenarios and saved results |
36
+
37
+ Separate goal portfolios share synchronized market scenarios. Fixed-rate savings accounts are
38
+ also supported, but are a different concept from investment portfolios for goals.
39
+ See [portfolio modes](docs/portfolio-modes.md) for allocation, transfers and funding rules.
40
+
41
+ ## Quick start
42
+
43
+ Use **Python 3.11+** and [Poetry](https://python-poetry.org/). From a local source checkout:
44
+
45
+ ```bash
46
+ git clone https://github.com/mbk-dev/okama-planner.git
47
+ cd okama-planner
48
+ poetry env use python3.11
49
+ poetry install --extras reports
50
+ poetry run python examples/demo.py
51
+ poetry run python examples/portfolio_modes.py
52
+ ```
53
+
54
+ The first example compares a purchase now versus a deferred purchase. The second compares a
55
+ pooled portfolio with home and retirement portfolios on the same synthetic market scenarios.
56
+ Requests, results and an Excel comparison are saved under `tmp/`; neither example downloads
57
+ market data or needs a client database.
58
+
59
+ **Prefer to browse first?** Open the [saved family inputs](examples/family-single-request.json),
60
+ [results](examples/family-single-result.json) and [Excel report examples](https://github.com/mbk-dev/okama-planner/releases/tag/v0.4.0).
61
+ The [three-goal hero input](examples/readme-request.json) and [result](examples/readme-result.json)
62
+ are included with [dated assumptions and validation metadata](examples/readme-metadata.json).
63
+ The USD example uses 5,000 Monte Carlo paths; its independent validation estimates plan success
64
+ at 95.92% under the supplied assumptions. For exact numerical replay, use the versions in [examples/versions.json](examples/versions.json);
65
+ a seed alone does not freeze data or dependencies. [Calculation contract →](docs/contract.md)
66
+
67
+ ### Use the Python API
68
+
69
+ ```python
70
+ import json
71
+ from pathlib import Path
72
+ from okama_planner import forecast
73
+
74
+ request = json.loads(Path("examples/readme-request.json").read_text())
75
+ result = forecast(request)
76
+ ```
77
+
78
+ The result is a JSON-compatible dictionary containing cash flows, goals, forecast metrics,
79
+ chart series and provenance. Complete input validation uses `ForecastRequest`; its JSON Schema
80
+ is available through `ForecastRequest.model_json_schema()`.
81
+
82
+ ## Reports & charts
83
+
84
+ ### Excel under your own brand
85
+
86
+ Set your company name, contacts, logo and accent color. The exporter creates a new workbook;
87
+ it does not require a private template or a pre-existing client file.
88
+
89
+ ```python
90
+ from okama_planner.reports import ReportBrand, export_report
91
+
92
+ export_report(
93
+ [{"label": "Family plan", "request": request, "result": result}],
94
+ "family-plan.xlsx",
95
+ brand=ReportBrand(company="Example Advisory", color="244C66"),
96
+ language="en", # en, ru, zh, de, es
97
+ )
98
+ ```
99
+
100
+ | Workbook sections | What they show |
101
+ |---|---|
102
+ | Summary, Budget, Balance | Plan outcomes, planned monthly cash flows, portfolio and net capital |
103
+ | Goals, Assumptions, Comparison | Goal funding, model inputs and differences between scenarios |
104
+ | Ledger | Detailed planned cash-flow requirements |
105
+ | Segments, Allocation, Segment balances | Portfolio assignments, strategies and account projections |
106
+ | Funding events, Transfers | Actual funded/unmet payments and transfers in joint portfolio modes |
107
+ | Branding, Instructions | Your presentation settings and guidance for reading the workbook |
108
+
109
+ The optional sheets reflect the result schema and portfolio mode. Excel presents saved forecast
110
+ results: editing a cell does not rerun Monte Carlo. Change the input, recalculate and export again.
111
+ [Report details and fictional-brand examples →](docs/reports.md)
112
+
113
+ ### Interactive and shareable charts
114
+
115
+ ```python
116
+ from okama_planner.charts import export_charts
117
+
118
+ export_charts(result, "charts") # offline interactive HTML
119
+ export_charts(result, "charts/png", format="png")
120
+ export_charts(result, "charts/svg", format="svg")
121
+ ```
122
+
123
+ Portfolio and net capital are separate charts. HTML includes hover values, goal markers,
124
+ logarithmic-scale controls and image download buttons. Direct PNG/SVG rendering requires
125
+ Chrome or Chromium; HTML generation does not. This is a **chart export**, not a complete
126
+ HTML financial-plan report or a hosted web application. [Chart options →](docs/charts.md)
127
+
128
+ ## Use with an AI assistant
129
+
130
+ Install Planner into the same environment as the existing **okama-mcp** server. Its current
131
+ source branch exposes `planner_forecast` and `planner_compare_modes`, while preserving the
132
+ existing portfolio tools. The adapter calls Planner rather than duplicating its calculations.
133
+
134
+ [Local installation, client setup and worked MCP examples →](https://github.com/mbk-dev/okama-mcp/blob/main/docs/planner.md)
135
+
136
+ Planner reports, chart rendering and consumption-utility helpers are not yet exposed through
137
+ these MCP tools. The published MCP package and public HTTP server have not been updated for
138
+ this integration; use the source installation described in the linked guide.
139
+
140
+ ## Client records
141
+
142
+ **Designed for professional client work by financial advisors and financial planners.**
143
+ The local SQLite registry brings client identity, contacts, broker relationships and
144
+ planning history together: one stable client record is linked to multiple versions of
145
+ financial inputs, scenarios and saved calculations. It supports ongoing work with a client,
146
+ from collecting information and choosing how to communicate to revisiting their financial plan.
147
+
148
+ **Status: implemented in the Python API.** `okama_planner.storage` provides client
149
+ creation, reading and updates, financial versions, scenarios and saved forecast results.
150
+ The shipped SQLite template contains schema and zero client records, plans or results.
151
+ Access to this registry through okama-mcp is a separate planned integration.
152
+
153
+ ```python
154
+ from pathlib import Path
155
+ from okama_planner.storage import PlannerStore
156
+
157
+ path = Path.home() / "planner-data" / "clients.sqlite3"
158
+ path.parent.mkdir(parents=True, exist_ok=True)
159
+ with PlannerStore.initialize(path) as store:
160
+ assert store.list_clients() == []
161
+ ```
162
+
163
+ `initialize` refuses to overwrite a file; `PlannerStore.open(path)` reopens an existing
164
+ database. [Storage API, versioned snapshots and migrations →](docs/storage.md)
165
+
166
+ ### Complete client record
167
+
168
+ The table below shows **all 16 columns of Planner's `client_registry`**, with three entirely
169
+ fictional records. Fields run down the table so the complete record remains readable.
170
+ These examples exist **only in this README**, not in a bundled database or a seed script.
171
+ They illustrate the registry supported by the storage API.
172
+
173
+ | Field | Alex Morgan | Priya Rao | Jordan Lee |
174
+ |---|---|---|---|
175
+ | `id` — internal identifier | 1 | 2 | 3 |
176
+ | `code` — stable client code | c-0001 | c-0002 | c-0003 |
177
+ | `full_name` — full name | Alex Morgan | Priya Rao | Jordan Lee |
178
+ | `sex` — recorded sex | male | female | — |
179
+ | `birth_year` — year of birth | 1985 | 1990 | 1978 |
180
+ | `email` — email address | alex@example.invalid | priya@example.invalid | jordan@example.invalid |
181
+ | `phone` — telephone | — | — | — |
182
+ | `telegram` — Telegram handle | — | — | — |
183
+ | `telegram_id` — stable numeric Telegram ID | — | — | — |
184
+ | `whatsapp` — WhatsApp contact | — | — | — |
185
+ | `max_messenger` — MAX messenger contact | — | — | — |
186
+ | `brokers` — ordered broker list | ["Example Broker A"] | [] | — |
187
+ | `primary_channel` — main communication channel | email | email | email |
188
+ | `ips_sent_at` — date the investment policy statement was sent | 2026-09-15 | — | 2026-10-01 |
189
+ | `note` — advisor's working notes | Annual plan review | First planning meeting | Retirement scenarios |
190
+ | `created_at` — record creation timestamp (UTC) | 2026-09-01T09:00:00Z | 2026-09-08T10:00:00Z | 2026-09-20T08:30:00Z |
191
+
192
+ A dash means the value has not been recorded. For `brokers`, an empty list means the client
193
+ explicitly has no broker; a missing value means this is unknown. `primary_channel` points to
194
+ a contact that has been filled in. `telegram_id` preserves identity when a handle changes.
195
+ `ips_sent_at` records delivery of the investment policy statement, not automatic document creation.
196
+
197
+ ### Identity, versions and planning history
198
+
199
+ The database separates the person from their changing financial information:
200
+
201
+ | Related table | All columns | Role in the advisor's workflow |
202
+ |---|---|---|
203
+ | `client` | `id`, `registry_id`, `version`, `source_digest`, `note`, `created_at` | A version of the client's financial inputs; linked by `registry_id`, with a source fingerprint |
204
+ | `tax_residency` | `id`, `registry_id`, `year`, `country`, `note` | Tax-residence country by calendar year, using an ISO two-letter country code |
205
+
206
+ Family members, assets, liabilities, budget items, goals, portfolios and scenarios belong to
207
+ versions of client financial data in Planner. Saved calculation runs hold the input snapshot and model settings.
208
+ This structure lets an advisor keep earlier inputs and compare later plans without treating
209
+ an updated financial situation as a different person. Recording tax residency does not itself
210
+ calculate jurisdiction-specific taxes.
211
+
212
+ Each advisor keeps their actual database outside the public repository. MCP access to the
213
+ registry remains planned; the storage API is implemented. Private advisory documents and internal
214
+ skills are not part of the public package.
215
+
216
+ ## Languages
217
+
218
+ **Available today:** Excel reports and chart interface text in **English, Russian,
219
+ German, Spanish and Simplified Chinese** (`en`, `ru`, `de`, `es`, `zh`). Select a language
220
+ with `export_report(..., language="ru")` or `export_charts(..., language="ru")`.
221
+ The shared [terminology table](src/okama_planner/terminology.csv) supplies translated captions.
222
+ See the [five-language report example](examples/multilingual_reports.py).
223
+
224
+ The broader localization roadmap covers:
225
+
226
+ - Excel and future HTML/PDF report headings, sheet names, instructions and template text.
227
+ - Chart titles, controls, annotations and number, currency and date formatting.
228
+ - Client-registry field labels, descriptions, forms and user-facing views.
229
+ - Validation messages, tool descriptions shown by MCP clients, guides and demonstration materials.
230
+ - Future web interface labels and help text.
231
+
232
+ SQL column names, JSON keys and API identifiers will remain stable across languages.
233
+ Client names and other user-entered text are not automatically translated. Localized wording
234
+ does not imply support for a country's tax or pension rules. Additional languages and localization beyond the implemented
235
+ Excel/chart captions are roadmap items until their implementation is published.
236
+
237
+ ## Model boundaries & next steps
238
+
239
+ The current model does not perform FX conversion or implement jurisdiction-specific taxes or
240
+ transaction fees. Inputs must already reflect externally modelled taxes and fees.
241
+ Monte Carlo probabilities describe the supplied model and assumptions, not guaranteed outcomes.
242
+
243
+ Retirement consumption **CE, gamma and equivalent-alpha helpers** exist as a separate module;
244
+ they are not yet integrated into forecasts, MCP or reports.
245
+ [Method and applicability →](docs/retirement-utility.md)
246
+
247
+ Next steps include registry access through MCP, broader MCP exports and multilingual presentation.
248
+ A web interface is a later direction. The standalone package contains no private client data,
249
+ MBK documents, internal skills or dependency on the closed lfp application.
250
+
251
+ Explore the family: [okama library](https://github.com/mbk-dev/okama) ·
252
+ [okama.io](https://okama.io/) · [okama-mcp](https://github.com/mbk-dev/okama-mcp).