fin-infra 0.1.92__py3-none-any.whl → 0.2.1__py3-none-any.whl
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.
- fin_infra/analytics/__init__.py +2 -2
- fin_infra/banking/history.py +4 -4
- fin_infra/brokerage/__init__.py +5 -5
- fin_infra/chat/planning.py +1 -1
- fin_infra/cli/cmds/scaffold_cmds.py +6 -6
- fin_infra/goals/management.py +3 -3
- fin_infra/goals/milestones.py +6 -6
- fin_infra/investments/scaffold_templates/README.md +17 -17
- fin_infra/net_worth/__init__.py +5 -5
- fin_infra/net_worth/insights.py +4 -4
- fin_infra/providers/brokerage/alpaca.py +1 -1
- fin_infra/tax/add.py +2 -2
- {fin_infra-0.1.92.dist-info → fin_infra-0.2.1.dist-info}/METADATA +3 -1
- {fin_infra-0.1.92.dist-info → fin_infra-0.2.1.dist-info}/RECORD +17 -17
- {fin_infra-0.1.92.dist-info → fin_infra-0.2.1.dist-info}/LICENSE +0 -0
- {fin_infra-0.1.92.dist-info → fin_infra-0.2.1.dist-info}/WHEEL +0 -0
- {fin_infra-0.1.92.dist-info → fin_infra-0.2.1.dist-info}/entry_points.txt +0 -0
fin_infra/analytics/__init__.py
CHANGED
|
@@ -8,8 +8,8 @@ This module provides comprehensive financial analytics capabilities including:
|
|
|
8
8
|
- Growth projections (net worth forecasting with scenarios)
|
|
9
9
|
|
|
10
10
|
Feature Status:
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
[OK] STABLE: Core calculation functions (all analytics work with provided data)
|
|
12
|
+
[!] INTEGRATION: Auto-fetching from providers requires setup:
|
|
13
13
|
- Banking provider for transaction data
|
|
14
14
|
- Brokerage provider for investment data
|
|
15
15
|
- Categorization for expense categorization
|
fin_infra/banking/history.py
CHANGED
|
@@ -4,7 +4,7 @@ This module provides functionality to record and retrieve historical account bal
|
|
|
4
4
|
snapshots over time. This enables balance trend analysis, sparklines, and time-series
|
|
5
5
|
visualizations in fintech dashboards.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
[!] WARNING: This module uses IN-MEMORY storage by default. All data is LOST on restart.
|
|
8
8
|
For production use, integrate with svc-infra SQL database or set FIN_INFRA_STORAGE_BACKEND.
|
|
9
9
|
|
|
10
10
|
Features:
|
|
@@ -57,7 +57,7 @@ __all__ = [
|
|
|
57
57
|
_logger = logging.getLogger(__name__)
|
|
58
58
|
|
|
59
59
|
# In-memory storage for testing (will be replaced with SQL database in production)
|
|
60
|
-
#
|
|
60
|
+
# [!] WARNING: All data is LOST on restart when using in-memory storage!
|
|
61
61
|
_balance_snapshots: list[BalanceSnapshot] = []
|
|
62
62
|
_production_warning_logged = False
|
|
63
63
|
|
|
@@ -73,7 +73,7 @@ def _check_in_memory_warning() -> None:
|
|
|
73
73
|
|
|
74
74
|
if env in ("production", "staging") and storage_backend == "memory":
|
|
75
75
|
_logger.warning(
|
|
76
|
-
"
|
|
76
|
+
"[!] CRITICAL: Balance history using IN-MEMORY storage in %s environment! "
|
|
77
77
|
"All balance snapshots will be LOST on restart. "
|
|
78
78
|
"Set FIN_INFRA_STORAGE_BACKEND=sql for production persistence.",
|
|
79
79
|
env,
|
|
@@ -114,7 +114,7 @@ def record_balance_snapshot(
|
|
|
114
114
|
This function stores a point-in-time balance record for trend analysis.
|
|
115
115
|
In production, this would write to a SQL database via svc-infra.
|
|
116
116
|
|
|
117
|
-
|
|
117
|
+
[!] WARNING: Uses in-memory storage by default. Data is LOST on restart!
|
|
118
118
|
|
|
119
119
|
Args:
|
|
120
120
|
account_id: Account identifier
|
fin_infra/brokerage/__init__.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Brokerage module - easy setup for trading operations.
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[!] **TRADING WARNING**: This module provides real trading capabilities.
|
|
4
4
|
Always use paper trading mode for development and testing.
|
|
5
5
|
Live trading requires explicit opt-in and involves real financial risk.
|
|
6
6
|
|
|
@@ -51,7 +51,7 @@ def easy_brokerage(
|
|
|
51
51
|
) -> BrokerageProvider:
|
|
52
52
|
"""Create a brokerage provider with paper/live trading support.
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
[!] **SAFETY**: Defaults to paper trading mode. Live trading requires explicit mode="live".
|
|
55
55
|
|
|
56
56
|
Auto-detects provider based on environment variables:
|
|
57
57
|
1. If ALPACA_API_KEY and ALPACA_API_SECRET are set → Alpaca
|
|
@@ -138,7 +138,7 @@ def add_brokerage(
|
|
|
138
138
|
) -> BrokerageProvider:
|
|
139
139
|
"""Wire brokerage provider to FastAPI app with routes and safety checks.
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
[!] **TRADING WARNING**: This mounts trading API endpoints.
|
|
142
142
|
Always use paper trading mode for development.
|
|
143
143
|
Live trading requires explicit mode="live" and proper safeguards.
|
|
144
144
|
|
|
@@ -280,7 +280,7 @@ def add_brokerage(
|
|
|
280
280
|
async def submit_order(order_request: OrderRequest):
|
|
281
281
|
"""Submit a new order.
|
|
282
282
|
|
|
283
|
-
|
|
283
|
+
[!] **TRADING WARNING**: This endpoint executes real trades in live mode.
|
|
284
284
|
"""
|
|
285
285
|
try:
|
|
286
286
|
order = brokerage_provider.submit_order(
|
|
@@ -447,7 +447,7 @@ def add_brokerage(
|
|
|
447
447
|
add_prefixed_docs(
|
|
448
448
|
app,
|
|
449
449
|
prefix=prefix,
|
|
450
|
-
title="Brokerage" + (" (Paper Trading)" if mode == "paper" else "
|
|
450
|
+
title="Brokerage" + (" (Paper Trading)" if mode == "paper" else " [!] LIVE"),
|
|
451
451
|
auto_exclude_from_root=True,
|
|
452
452
|
visible_envs=None, # Show in all environments
|
|
453
453
|
)
|
fin_infra/chat/planning.py
CHANGED
|
@@ -173,7 +173,7 @@ Answer: "To assess your retirement progress, I need more information: (1) What's
|
|
|
173
173
|
Follow-ups: ["I want to retire at 65 with $1.5M", "How much should I save monthly?", "What's a realistic retirement goal?"]
|
|
174
174
|
Sources: []
|
|
175
175
|
|
|
176
|
-
|
|
176
|
+
[!] This is AI-generated advice. Not a substitute for a certified financial advisor.
|
|
177
177
|
Verify calculations independently. For personalized advice, consult a professional."""
|
|
178
178
|
|
|
179
179
|
|
|
@@ -102,7 +102,7 @@ def cmd_scaffold(
|
|
|
102
102
|
# Validate required parameters
|
|
103
103
|
if dest_dir is None:
|
|
104
104
|
typer.secho(
|
|
105
|
-
"
|
|
105
|
+
"[X] Error: --dest-dir is required",
|
|
106
106
|
fg=typer.colors.RED,
|
|
107
107
|
err=True,
|
|
108
108
|
)
|
|
@@ -137,7 +137,7 @@ def cmd_scaffold(
|
|
|
137
137
|
)
|
|
138
138
|
else:
|
|
139
139
|
typer.secho(
|
|
140
|
-
f"
|
|
140
|
+
f"[X] Unknown domain: {domain}. Must be one of: budgets, goals",
|
|
141
141
|
fg=typer.colors.RED,
|
|
142
142
|
err=True,
|
|
143
143
|
)
|
|
@@ -145,7 +145,7 @@ def cmd_scaffold(
|
|
|
145
145
|
|
|
146
146
|
# Display results
|
|
147
147
|
typer.echo("")
|
|
148
|
-
typer.secho("
|
|
148
|
+
typer.secho(" Scaffold Results:", bold=True)
|
|
149
149
|
typer.echo("")
|
|
150
150
|
|
|
151
151
|
files = result.get("files", [])
|
|
@@ -157,7 +157,7 @@ def cmd_scaffold(
|
|
|
157
157
|
action = file_info.get("action", "unknown")
|
|
158
158
|
|
|
159
159
|
if action == "wrote":
|
|
160
|
-
typer.secho(f"
|
|
160
|
+
typer.secho(f" [OK] Created: {path}", fg=typer.colors.GREEN)
|
|
161
161
|
wrote_count += 1
|
|
162
162
|
elif action == "skipped":
|
|
163
163
|
reason = file_info.get("reason", "unknown")
|
|
@@ -168,7 +168,7 @@ def cmd_scaffold(
|
|
|
168
168
|
|
|
169
169
|
# Summary
|
|
170
170
|
typer.echo("")
|
|
171
|
-
typer.secho(f"
|
|
171
|
+
typer.secho(f" Done! Created {wrote_count} file(s), skipped {skipped_count}.", bold=True)
|
|
172
172
|
typer.echo("")
|
|
173
173
|
|
|
174
174
|
# Next steps
|
|
@@ -187,7 +187,7 @@ def cmd_scaffold(
|
|
|
187
187
|
}
|
|
188
188
|
route_prefix = prefix_map.get(domain, f"/{domain}")
|
|
189
189
|
|
|
190
|
-
typer.secho("
|
|
190
|
+
typer.secho(" Next Steps:", bold=True)
|
|
191
191
|
typer.echo("")
|
|
192
192
|
typer.echo(" 1. Review generated files and customize as needed")
|
|
193
193
|
typer.echo(" 2. Run migrations:")
|
fin_infra/goals/management.py
CHANGED
|
@@ -182,7 +182,7 @@ Your response: {
|
|
|
182
182
|
"confidence": 0.94
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
-
|
|
185
|
+
[!] This is AI-generated advice. Not a substitute for a certified financial advisor.
|
|
186
186
|
Verify calculations independently. For personalized advice, consult a professional."""
|
|
187
187
|
|
|
188
188
|
GOAL_PROGRESS_SYSTEM_PROMPT = """You are a financial advisor reviewing goal progress.
|
|
@@ -237,7 +237,7 @@ Your response: {
|
|
|
237
237
|
"projected_completion_date": "2029-06-01",
|
|
238
238
|
"variance_from_target_days": -365,
|
|
239
239
|
"course_corrections": [
|
|
240
|
-
"
|
|
240
|
+
"[!] 12 months behind! Current $1,000/month payment needs to increase to $1,500/month",
|
|
241
241
|
"Emergency: reduce expenses by $500/month (cancel subscriptions, cut entertainment)",
|
|
242
242
|
"Contact debt counselor for consolidation or negotiation options",
|
|
243
243
|
"Consider side income: gig work, selling unused items ($500/month target)",
|
|
@@ -246,7 +246,7 @@ Your response: {
|
|
|
246
246
|
"confidence": 0.95
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
-
|
|
249
|
+
[!] This is AI-generated advice. Not a substitute for a certified financial advisor.
|
|
250
250
|
Verify calculations independently. For personalized advice, consult a professional."""
|
|
251
251
|
|
|
252
252
|
|
fin_infra/goals/milestones.py
CHANGED
|
@@ -22,7 +22,7 @@ Example:
|
|
|
22
22
|
# Check which milestones have been reached
|
|
23
23
|
reached = check_milestones("goal_123")
|
|
24
24
|
for m in reached:
|
|
25
|
-
print(f"
|
|
25
|
+
print(f" Milestone reached: {m['description']}")
|
|
26
26
|
"""
|
|
27
27
|
|
|
28
28
|
from datetime import datetime
|
|
@@ -124,7 +124,7 @@ def check_milestones(goal_id: str) -> list[dict[str, Any]]:
|
|
|
124
124
|
|
|
125
125
|
reached = check_milestones("goal_123")
|
|
126
126
|
if reached:
|
|
127
|
-
print(f"
|
|
127
|
+
print(f" {len(reached)} milestones reached!")
|
|
128
128
|
for m in reached:
|
|
129
129
|
print(f" - {m['description']}: ${m['amount']:,.0f}")
|
|
130
130
|
|
|
@@ -184,17 +184,17 @@ def get_celebration_message(milestone: dict[str, Any]) -> str:
|
|
|
184
184
|
|
|
185
185
|
Example:
|
|
186
186
|
message = get_celebration_message(milestone)
|
|
187
|
-
# "
|
|
187
|
+
# " Milestone reached! You've hit $25,000 - 25% to target!"
|
|
188
188
|
"""
|
|
189
189
|
amount = milestone["amount"]
|
|
190
190
|
description = milestone["description"]
|
|
191
191
|
|
|
192
192
|
messages = [
|
|
193
|
-
f"
|
|
193
|
+
f" Milestone reached! You've hit ${amount:,.0f} - {description}!",
|
|
194
194
|
f"🎊 Congratulations! ${amount:,.0f} milestone achieved - {description}",
|
|
195
195
|
f"🌟 Great progress! You reached ${amount:,.0f} - {description}",
|
|
196
|
-
f"
|
|
197
|
-
f"
|
|
196
|
+
f" Keep going! ${amount:,.0f} milestone completed - {description}",
|
|
197
|
+
f" Amazing! You hit ${amount:,.0f} - {description}",
|
|
198
198
|
]
|
|
199
199
|
|
|
200
200
|
# Use amount to pick consistent message for same milestone
|
|
@@ -18,15 +18,15 @@ These templates generate production-ready persistence code for investment holdin
|
|
|
18
18
|
## Why Historical Snapshots?
|
|
19
19
|
|
|
20
20
|
**Investment data providers (Plaid, SnapTrade, etc.) only provide current/live data:**
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
21
|
+
- [X] No historical portfolio values from past dates
|
|
22
|
+
- [X] No historical performance metrics
|
|
23
|
+
- [X] Cannot answer "What was my portfolio worth 3 months ago?"
|
|
24
24
|
|
|
25
25
|
**Solution: Store periodic snapshots in your database**
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
26
|
+
- [OK] Track portfolio value changes over time
|
|
27
|
+
- [OK] Calculate performance metrics (returns, growth)
|
|
28
|
+
- [OK] Show trend charts and historical analysis
|
|
29
|
+
- [OK] Works even if user disconnects provider
|
|
30
30
|
|
|
31
31
|
## Template Variables
|
|
32
32
|
|
|
@@ -148,12 +148,12 @@ async def capture_holdings_snapshot(
|
|
|
148
148
|
holdings_data: list[dict], # From Plaid/SnapTrade API
|
|
149
149
|
) -> None:
|
|
150
150
|
"""Capture current holdings as a snapshot for historical tracking."""
|
|
151
|
-
|
|
151
|
+
|
|
152
152
|
# Calculate aggregated metrics
|
|
153
153
|
total_value = sum(Decimal(str(h.get("institution_value", 0))) for h in holdings_data)
|
|
154
154
|
total_cost_basis = sum(Decimal(str(h.get("cost_basis", 0))) for h in holdings_data if h.get("cost_basis"))
|
|
155
155
|
total_unrealized_gain_loss = sum(Decimal(str(h.get("unrealized_gain_loss", 0))) for h in holdings_data if h.get("unrealized_gain_loss"))
|
|
156
|
-
|
|
156
|
+
|
|
157
157
|
# Create snapshot
|
|
158
158
|
service = create_holding_snapshot_service(session)
|
|
159
159
|
snapshot = await service.create(HoldingSnapshotCreate(
|
|
@@ -167,7 +167,7 @@ async def capture_holdings_snapshot(
|
|
|
167
167
|
provider="plaid", # or "snaptrade"
|
|
168
168
|
notes="Automatic daily snapshot"
|
|
169
169
|
))
|
|
170
|
-
|
|
170
|
+
|
|
171
171
|
await session.commit()
|
|
172
172
|
```
|
|
173
173
|
|
|
@@ -181,18 +181,18 @@ async def daily_holdings_snapshot():
|
|
|
181
181
|
"""Capture holdings snapshots for all users with investment accounts."""
|
|
182
182
|
from sqlalchemy import select
|
|
183
183
|
from my_app.models.user import User
|
|
184
|
-
|
|
184
|
+
|
|
185
185
|
async with AsyncSession(engine) as session:
|
|
186
186
|
# Get all users with Plaid/SnapTrade connections
|
|
187
187
|
stmt = select(User).where(User.banking_providers.isnot(None))
|
|
188
188
|
result = await session.execute(stmt)
|
|
189
189
|
users = result.scalars().all()
|
|
190
|
-
|
|
190
|
+
|
|
191
191
|
for user in users:
|
|
192
192
|
try:
|
|
193
193
|
# Fetch current holdings from provider
|
|
194
194
|
holdings = await fetch_holdings_from_provider(user)
|
|
195
|
-
|
|
195
|
+
|
|
196
196
|
# Create snapshot
|
|
197
197
|
await capture_holdings_snapshot(session, user.id, holdings)
|
|
198
198
|
except Exception as e:
|
|
@@ -299,10 +299,10 @@ async def get_portfolio_performance_data(user_id: str):
|
|
|
299
299
|
"""Get data for portfolio performance dashboard."""
|
|
300
300
|
async with AsyncSession(engine) as session:
|
|
301
301
|
repo = create_holding_snapshot_service(session)
|
|
302
|
-
|
|
302
|
+
|
|
303
303
|
# Get last 12 months trend
|
|
304
304
|
snapshots = await repo.get_trend(user_id=user_id, months=12)
|
|
305
|
-
|
|
305
|
+
|
|
306
306
|
# Calculate YTD performance
|
|
307
307
|
today = date.today()
|
|
308
308
|
year_start = date(today.year, 1, 1)
|
|
@@ -311,10 +311,10 @@ async def get_portfolio_performance_data(user_id: str):
|
|
|
311
311
|
start_date=year_start,
|
|
312
312
|
end_date=today
|
|
313
313
|
)
|
|
314
|
-
|
|
314
|
+
|
|
315
315
|
# Get latest snapshot
|
|
316
316
|
latest = await repo.get_latest(user_id=user_id)
|
|
317
|
-
|
|
317
|
+
|
|
318
318
|
return {
|
|
319
319
|
"current_value": latest.total_value if latest else 0,
|
|
320
320
|
"ytd_return": ytd_performance["percent_return"],
|
fin_infra/net_worth/__init__.py
CHANGED
|
@@ -5,11 +5,11 @@ Calculates net worth by aggregating balances from multiple financial providers
|
|
|
5
5
|
(banking, brokerage, crypto) with historical snapshots and change detection.
|
|
6
6
|
|
|
7
7
|
**Feature Status**:
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
[OK] STABLE: Core calculation (works with provided data)
|
|
9
|
+
[OK] STABLE: Banking integration (Plaid, Teller)
|
|
10
|
+
[!] INTEGRATION: Brokerage integration (requires provider setup)
|
|
11
|
+
[!] INTEGRATION: Crypto integration (requires provider setup)
|
|
12
|
+
[!] INTEGRATION: Currency conversion (pass exchange_rate manually)
|
|
13
13
|
|
|
14
14
|
**Key Features**:
|
|
15
15
|
- Multi-provider aggregation (banking + brokerage + crypto)
|
fin_infra/net_worth/insights.py
CHANGED
|
@@ -215,7 +215,7 @@ Response: {
|
|
|
215
215
|
"confidence": 0.89
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
-
|
|
218
|
+
[!] This is AI-generated advice. Not a substitute for a certified financial advisor.
|
|
219
219
|
Verify calculations independently. For personalized advice, consult a professional."""
|
|
220
220
|
|
|
221
221
|
DEBT_REDUCTION_SYSTEM_PROMPT = """You are a debt counselor using the avalanche method (highest APR first).
|
|
@@ -269,7 +269,7 @@ Response: {
|
|
|
269
269
|
"confidence": 0.98
|
|
270
270
|
}
|
|
271
271
|
|
|
272
|
-
|
|
272
|
+
[!] This is AI-generated advice. Not a substitute for a certified financial advisor.
|
|
273
273
|
Verify calculations independently. For personalized advice, consult a professional."""
|
|
274
274
|
|
|
275
275
|
GOAL_RECOMMENDATION_SYSTEM_PROMPT = """You are a financial planner validating goals and suggesting paths.
|
|
@@ -322,7 +322,7 @@ Response: {
|
|
|
322
322
|
"confidence": 0.89
|
|
323
323
|
}
|
|
324
324
|
|
|
325
|
-
|
|
325
|
+
[!] This is AI-generated advice. Not a substitute for a certified financial advisor.
|
|
326
326
|
Verify calculations independently. For personalized advice, consult a professional."""
|
|
327
327
|
|
|
328
328
|
ASSET_ALLOCATION_SYSTEM_PROMPT = """You are a portfolio advisor recommending asset allocation.
|
|
@@ -365,7 +365,7 @@ Response: {
|
|
|
365
365
|
"confidence": 0.91
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
-
|
|
368
|
+
[!] This is AI-generated advice. Not a substitute for a certified financial advisor.
|
|
369
369
|
Verify calculations independently. For personalized advice, consult a professional."""
|
|
370
370
|
|
|
371
371
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Alpaca brokerage provider for paper and live trading.
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[!] IMPORTANT: This module provides real trading capabilities. Always use paper trading
|
|
4
4
|
mode for development and testing. Live trading requires explicit opt-in.
|
|
5
5
|
"""
|
|
6
6
|
|
fin_infra/tax/add.py
CHANGED
|
@@ -279,7 +279,7 @@ def add_tax_data(
|
|
|
279
279
|
that can be sold to offset capital gains. Suggests replacement securities
|
|
280
280
|
to maintain market exposure without triggering wash sale rules.
|
|
281
281
|
|
|
282
|
-
|
|
282
|
+
[!] **DISCLAIMER**: Not a substitute for professional tax or financial advice.
|
|
283
283
|
Consult a certified tax professional before executing TLH trades.
|
|
284
284
|
|
|
285
285
|
Args:
|
|
@@ -344,7 +344,7 @@ def add_tax_data(
|
|
|
344
344
|
Projects the outcome of executing provided TLH opportunities, including
|
|
345
345
|
total tax savings, portfolio impact, and risk assessment.
|
|
346
346
|
|
|
347
|
-
|
|
347
|
+
[!] **DISCLAIMER**: Not a substitute for professional tax or financial advice.
|
|
348
348
|
Consult a certified tax professional before executing TLH trades.
|
|
349
349
|
|
|
350
350
|
Args:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: fin-infra
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Financial infrastructure toolkit: banking connections, market data, credit, cashflows, and brokerage integrations
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: finance,banking,plaid,brokerage,markets,credit,tax,cashflow,fintech,infra
|
|
@@ -28,7 +28,9 @@ Provides-Extra: yahoo
|
|
|
28
28
|
Requires-Dist: ai-infra (>=0.1.142)
|
|
29
29
|
Requires-Dist: cashews[redis] (>=7.0)
|
|
30
30
|
Requires-Dist: ccxt (>=4.0.0) ; extra == "markets" or extra == "crypto" or extra == "all"
|
|
31
|
+
Requires-Dist: fastapi-users (>=15.0.2,<16.0.0)
|
|
31
32
|
Requires-Dist: httpx (>=0.25.0)
|
|
33
|
+
Requires-Dist: langchain-core (>=1.2.5,<2.0.0)
|
|
32
34
|
Requires-Dist: loguru (>=0.7.0)
|
|
33
35
|
Requires-Dist: numpy (>=1.24.0)
|
|
34
36
|
Requires-Dist: numpy-financial (>=1.0.0)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
fin_infra/__init__.py,sha256=7oL-CCsALNifBODAn9LriicaIrzgJkmVPvE-9duP0mw,1574
|
|
2
2
|
fin_infra/__main__.py,sha256=1qNP7j0ffw0wFs1dBwDcJ9TNXlC6FcYuulzoV87pMi8,262
|
|
3
|
-
fin_infra/analytics/__init__.py,sha256
|
|
3
|
+
fin_infra/analytics/__init__.py,sha256=-OsQUqLgOdafSNzbcIHy3G37nX2OwD0OzGj8C2Aiufs,2325
|
|
4
4
|
fin_infra/analytics/add.py,sha256=-iAqKdvf9t0gQjjo3uOO56qA_ei4omKYDOynxb4SZPI,12654
|
|
5
5
|
fin_infra/analytics/cash_flow.py,sha256=VSsQHwTi6r6VFoScH9nu9Fj8XHC4O4B9TkAI8Alobm4,10284
|
|
6
6
|
fin_infra/analytics/ease.py,sha256=aTAPc-Lmh6XP7REPVlAom38MtKCqeS-auNW-rpXRZJs,14282
|
|
@@ -12,9 +12,9 @@ fin_infra/analytics/savings.py,sha256=n3rGNFP8TU5mW-uz9kOuqX_mDiVnDyAeDN06Q7Abot
|
|
|
12
12
|
fin_infra/analytics/scenarios.py,sha256=LE_dZVkbxxAx5sxitGhiOhZfWTlYtVbIvS9pEXkijLc,12246
|
|
13
13
|
fin_infra/analytics/spending.py,sha256=ogLcfF5ZOLMkBIj02RISnA3hiY_PsLWZ2_AAzA7FenY,26209
|
|
14
14
|
fin_infra/banking/__init__.py,sha256=6wwGNITzyehC9MBQc5jy0ewSTuNetyQu2AdND51O55w,22450
|
|
15
|
-
fin_infra/banking/history.py,sha256=
|
|
15
|
+
fin_infra/banking/history.py,sha256=YB-v9A03IZ_qki6A6mA-RO5Y4imlqk1CyP0W482ufdQ,10563
|
|
16
16
|
fin_infra/banking/utils.py,sha256=HhxZbeaA8zqVttgMiJGnShTo_r_0DaD7T3IMq8n8340,15252
|
|
17
|
-
fin_infra/brokerage/__init__.py,sha256=
|
|
17
|
+
fin_infra/brokerage/__init__.py,sha256=Z5w1vWqETaajWNFPJ3DbHscVpqjlkKtDAJ6O8JgS7Tg,17139
|
|
18
18
|
fin_infra/budgets/__init__.py,sha256=GgfujfgdVld6_yUf8bhkW-bsIXBLb4THlJMocVpA4mM,3986
|
|
19
19
|
fin_infra/budgets/add.py,sha256=i7Av--Z14sYQDJHETiF9VL71ouWBZcs3H3VZ62gqFEo,13508
|
|
20
20
|
fin_infra/budgets/alerts.py,sha256=XDSUPpRR1LNgSQU0Szlht0bLWI7RRBh1ElbcwGexbPs,9701
|
|
@@ -39,10 +39,10 @@ fin_infra/categorization/rules.py,sha256=IpDnHBeuykRdu5vs3Lph4Y9-3RseIjjleQ5hZph
|
|
|
39
39
|
fin_infra/categorization/taxonomy.py,sha256=p-tSOwJ0O-rFZ1LIlHSYdaYdSc65084j0fdMI_6LW84,13251
|
|
40
40
|
fin_infra/chat/__init__.py,sha256=-gufQz-rOZVXkcTUcCcXdG2oGL8csJBxwSuOMN_5aVc,6324
|
|
41
41
|
fin_infra/chat/ease.py,sha256=8T0BQUkWQVpaTooD5-ZtinackkciqGargXnzWzayj3M,3113
|
|
42
|
-
fin_infra/chat/planning.py,sha256=
|
|
42
|
+
fin_infra/chat/planning.py,sha256=goXAHQFv-du89wAHw_X_vm8aF7-HGBeRlyiA_BWx5xw,19912
|
|
43
43
|
fin_infra/cli/__init__.py,sha256=7M8gKULnui4__9kXRKRHgETuFwZlacK9xrq5rSZ31CM,376
|
|
44
44
|
fin_infra/cli/cmds/__init__.py,sha256=BvL3wRoUl3cO5wesv1Cqoatup7VeYMhq82tS19iNZHE,136
|
|
45
|
-
fin_infra/cli/cmds/scaffold_cmds.py,sha256=
|
|
45
|
+
fin_infra/cli/cmds/scaffold_cmds.py,sha256=bbVSNmnePOS5lqPH1Wq0ohiQWV3UnX_uTIjQkAr5qjs,7564
|
|
46
46
|
fin_infra/clients/__init__.py,sha256=CL_NUNxLAKFvG7wL_F-rAhUucp6pm0sNHVtvCzVvLcw,708
|
|
47
47
|
fin_infra/clients/base.py,sha256=fZebDGIfQQybqeXpFpORlDZ6wSKf33aIAkUUpmyvZrA,979
|
|
48
48
|
fin_infra/clients/plaid.py,sha256=0_kV95vDgasbWyVQe3OEqtVXkF4Q6SNmvHwXXY0gzh8,816
|
|
@@ -68,8 +68,8 @@ fin_infra/exceptions.py,sha256=k7L3vfXcONM2-AqmqNhQvOHobVBrLPTYp44cMUxuP3o,16951
|
|
|
68
68
|
fin_infra/goals/__init__.py,sha256=iiy7qkPazSSAmPFhy2EXkfJvOBfb7ymrqS1eXBNiaQc,2130
|
|
69
69
|
fin_infra/goals/add.py,sha256=zobcqEsEzsmd9itSPyPmzpkzFQYZlETo9d17bU9s3mc,20534
|
|
70
70
|
fin_infra/goals/funding.py,sha256=Fw6hUvb8yNWineEbRXFYgw4_ZRnGrBSChBjkb7Qozrs,9303
|
|
71
|
-
fin_infra/goals/management.py,sha256=
|
|
72
|
-
fin_infra/goals/milestones.py,sha256=
|
|
71
|
+
fin_infra/goals/management.py,sha256=1Ur76J6-EoxIbLZVnyfw64F4wwTq8Sp5e-YWDk5qVP4,33859
|
|
72
|
+
fin_infra/goals/milestones.py,sha256=1Sq-ZbW_H9Makw-kz4ekuw5kFGeDBNgnyTy-1Lr9TQo,9972
|
|
73
73
|
fin_infra/goals/models.py,sha256=5X0BddvK9FBsXMTXBQn8YFBNLtIbXue9a4VdLH3rWR8,10173
|
|
74
74
|
fin_infra/goals/scaffold_templates/README.md,sha256=CoE_3I2K32orOFH6CvfVBaJBTGDYIESd5-48V7vU1FI,9974
|
|
75
75
|
fin_infra/goals/scaffold_templates/__init__.py,sha256=rLFam-mRsj8LvJu5kRBEIJtw9rFUof7KApgD2IRE56c,107
|
|
@@ -87,7 +87,7 @@ fin_infra/investments/providers/__init__.py,sha256=V1eIzz6EnGJ-pq-9L3S2-evmcExF-
|
|
|
87
87
|
fin_infra/investments/providers/base.py,sha256=1plM-o_fV6jQyyPnpZT5q8ir96oyxvh0zwA3qpiVIFY,9810
|
|
88
88
|
fin_infra/investments/providers/plaid.py,sha256=X42cMpsHNcOPcYvl73jrP8x7nQ399n2_it3Ko9UIkI0,18751
|
|
89
89
|
fin_infra/investments/providers/snaptrade.py,sha256=Hs5uM3F31mGzSONgVXLlL2BR86mjOWs8OhcpLiUeaAo,23251
|
|
90
|
-
fin_infra/investments/scaffold_templates/README.md,sha256=
|
|
90
|
+
fin_infra/investments/scaffold_templates/README.md,sha256=q9xB__7xqSK5JTvzsDDHMsFirwWV-7TNn45R0k9F2aE,12081
|
|
91
91
|
fin_infra/investments/scaffold_templates/__init__.py,sha256=iR0oiAzXFYXHBnVJjaEnAzk6omncYOLg0TKMJ7xomBc,82
|
|
92
92
|
fin_infra/investments/scaffold_templates/models.py.tmpl,sha256=5inP5-jw-qEfPYxSN71tn4AojZ9PesOIeuHTw181N-c,5849
|
|
93
93
|
fin_infra/investments/scaffold_templates/repository.py.tmpl,sha256=XwOEpQZfuXut1WLiq-GSSvv0oX0iYCW54eJNL0Cav94,14656
|
|
@@ -102,13 +102,13 @@ fin_infra/models/money.py,sha256=63pdGD1WBMHicJ1w7pbU1g5fqt4gIzPuqQQ2-NSlBuc,401
|
|
|
102
102
|
fin_infra/models/quotes.py,sha256=-YBzgnjjCihRAprUdaPRtfwKrgliDIGgqAnaM69VbDU,521
|
|
103
103
|
fin_infra/models/tax.py,sha256=as40J9h24BB7LmeaIfay509UaYEctmk5CPW9CfcjWZc,15657
|
|
104
104
|
fin_infra/models/transactions.py,sha256=gzc6hLKKU6VUWGshqw2WChU_x0qyXhdvOGwmj9H_H3I,790
|
|
105
|
-
fin_infra/net_worth/__init__.py,sha256=
|
|
105
|
+
fin_infra/net_worth/__init__.py,sha256=mTus1Y_JCwWuWMstbkQVlxIJqZa2SWRn3ERUTFVH9xg,3445
|
|
106
106
|
fin_infra/net_worth/add.py,sha256=QWfHIHJs2CV99WRBqjQ2OteiOrn5cR9nurmxTF9v5rg,23191
|
|
107
107
|
fin_infra/net_worth/aggregator.py,sha256=9Kx2vUR71QwqYZdGaCfmYrJ1hNxzd1EEuAdWJoNjqTI,12780
|
|
108
108
|
fin_infra/net_worth/calculator.py,sha256=SQJGJDok5HgvoAhKBxeeqt8vhGMchABU3zPmNRpqNy4,13139
|
|
109
109
|
fin_infra/net_worth/ease.py,sha256=ERdFrUjjb5l5BRp_c2tEfE1obTpRc_-FA9LnV7BTiEw,15883
|
|
110
110
|
fin_infra/net_worth/goals.py,sha256=BJGxdsMjvgQDELFEJo-ai3DvsAzUNXvzMXkwovHr8yQ,1238
|
|
111
|
-
fin_infra/net_worth/insights.py,sha256=
|
|
111
|
+
fin_infra/net_worth/insights.py,sha256=MdZHrwk4T0WNNIo97DroNelQBDoBr9z70VS05yBXqb8,25209
|
|
112
112
|
fin_infra/net_worth/models.py,sha256=sZv3dGw5zwckE2XQ7n5ehK7sv4jdGCo9c2g4ZtZHwCI,26880
|
|
113
113
|
fin_infra/net_worth/scaffold_templates/README.md,sha256=Wqd6ksqFjmtNdDFOWVV_duuAcePWwiu3_YgkVM9N_WY,14363
|
|
114
114
|
fin_infra/net_worth/scaffold_templates/__init__.py,sha256=OKeMCC_JNw6m8rBWr_wesOIJ1OR9LCBeIkXKahbCGC4,132
|
|
@@ -129,7 +129,7 @@ fin_infra/providers/banking/base.py,sha256=KeNU4ur3zLKHVsBF1LQifcs2AKX06IEE-Rx_S
|
|
|
129
129
|
fin_infra/providers/banking/plaid_client.py,sha256=8Nvd9Ow_v6Scnw79R86uSvRcBRHPgc3ytsQze50E7aM,6524
|
|
130
130
|
fin_infra/providers/banking/teller_client.py,sha256=733Eq-o9Yt7Sm_aWOeunJU4EWYRAaZNS7vgDVGqR0W4,10279
|
|
131
131
|
fin_infra/providers/base.py,sha256=Tqjl5_hSTShgYLrSiKzeDbnL_I-dji-G_itkumm15IM,7722
|
|
132
|
-
fin_infra/providers/brokerage/alpaca.py,sha256=
|
|
132
|
+
fin_infra/providers/brokerage/alpaca.py,sha256=BObiI_dFQZ3fOpTfmZMkri8sVrsz5uW6i5ZVUb0etCU,9923
|
|
133
133
|
fin_infra/providers/brokerage/base.py,sha256=JJFH0Cqca4Rg4rmxfiwcQt-peRoBf4JpG3g6jx8DVks,106
|
|
134
134
|
fin_infra/providers/credit/experian.py,sha256=r7lpFecgOdNEhb_Lxz2Z-BG8R3p2n0XlqDKL7y8NZ-0,482
|
|
135
135
|
fin_infra/providers/identity/stripe_identity.py,sha256=JQGJRuQdWP5dWDcROgtz1RrmpkytRv95H6Fn-x1kifU,501
|
|
@@ -167,15 +167,15 @@ fin_infra/security/pii_patterns.py,sha256=SM-o7cL6NdgkOmtBedsN2nJZ5QPbeYehZdYmAu
|
|
|
167
167
|
fin_infra/security/token_store.py,sha256=FsfoAkIMQ2NRfkBuyG1eH30nnfO3w_V5tDPAZwUj9Os,6041
|
|
168
168
|
fin_infra/settings.py,sha256=11JgIhjGwWnwixV-hveEWpoWd_JC0ixLnOQoLWCiwNo,1387
|
|
169
169
|
fin_infra/tax/__init__.py,sha256=U0EUKQwbDqnAYwU8WRx6AD07TaB-ELdKGISOQ-904lw,6103
|
|
170
|
-
fin_infra/tax/add.py,sha256=
|
|
170
|
+
fin_infra/tax/add.py,sha256=d17Zuoi-xMjuJNykDHzQXnAUVzd_41BUMHQdqm23jJ8,14547
|
|
171
171
|
fin_infra/tax/tlh.py,sha256=3khtiEkGKIIHi2mbMM0ss-GKQ8vM3FS6hly8R00qseY,21482
|
|
172
172
|
fin_infra/utils/__init__.py,sha256=x_FUlv7FONdTPHwXTbPWY-EEOBwWnm-y8TPJ1W1PrXM,944
|
|
173
173
|
fin_infra/utils/deprecation.py,sha256=DTcqv7ECnrWOOwoA07JOnRci4Hqqo9YtKSSmoS-DVPY,5187
|
|
174
174
|
fin_infra/utils/http.py,sha256=rDEgYsEBrEe75ml5RA-iSs3xeU5W-3j-czJlT7WbrM4,632
|
|
175
175
|
fin_infra/utils/retry.py,sha256=YiyTgy26eJ1ah7fE2_-ZPa4hv4bIT4OzjYolkNWb5j0,1057
|
|
176
176
|
fin_infra/version.py,sha256=4t_crzhrLum--oyowUMxtjBTzUtWp7oRTF22ewEvJG4,49
|
|
177
|
-
fin_infra-0.1.
|
|
178
|
-
fin_infra-0.1.
|
|
179
|
-
fin_infra-0.1.
|
|
180
|
-
fin_infra-0.1.
|
|
181
|
-
fin_infra-0.1.
|
|
177
|
+
fin_infra-0.2.1.dist-info/LICENSE,sha256=wK-Ya7Ylxa38dSIZRhvNj1ZVLIrHC-BAI8v38PNADiA,1061
|
|
178
|
+
fin_infra-0.2.1.dist-info/METADATA,sha256=NdGFOF-FPeuEB_BxH8xAhdKjvjdYycn6akhJ9COg0wo,10806
|
|
179
|
+
fin_infra-0.2.1.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
|
180
|
+
fin_infra-0.2.1.dist-info/entry_points.txt,sha256=Sr1uikvALZMeKm-DIkeKG4L9c4SNqysXGO_IRF8_9eU,53
|
|
181
|
+
fin_infra-0.2.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|