A complete web application for managing leveraged investment portfolios that implements a Conditional DCA and Dynamic Leverage Management strategy. The application allows users to manage leveraged portfolios with automated rebalancing strategies based on market signals, Sharpe Ratio optimization, and active risk management.
Margn implements an investment strategy where:
- Users make periodic contributions (DCA - Dollar Cost Averaging)
- The system automatically manages leverage between 2.5x and 4.0x
- Asset weights are optimized using Sharpe Ratio algorithms
- Contributions are deployed conditionally based on market signals (drawdown, weight deviation, volatility)
- Clear recommendations and specific actions are provided to keep the portfolio within configured risk parameters
The strategy is based on quantitative analysis from the leveraged-dca-simulator project, using Monte Carlo simulation and historical backtesting to optimize leveraged portfolios.
margn/
โโโ apps/
โ โโโ backend/ # NestJS API (Port 3003)
โ โโโ frontend/ # Next.js Dashboard (Port 3002)
โโโ packages/
โ โโโ shared/ # Shared types and utilities
โโโ infra/
โโโ scripts/ # Scheduled jobs (cron)
Backend:
- NestJS 10.2.0
- Prisma ORM (PostgreSQL)
- Supabase (Auth + Database)
- TypeScript
Frontend:
- Next.js 14
- React 19
- TypeScript
- Supabase Client
Infrastructure:
- Supabase (PostgreSQL + Auth)
- Render/Railway (Backend hosting)
- Vercel (Frontend hosting)
- Node.js 18+
- npm or yarn
- PostgreSQL database (Supabase)
# Install dependencies
npm install
# Sync database schema
cd apps/backend
npm run prisma:push
npm run prisma:generateBackend (apps/backend/.env):
DATABASE_URL=postgresql://postgres:[PASSWORD]@db.xxx.supabase.co:5432/postgres
DIRECT_URL=postgresql://postgres:[PASSWORD]@db.xxx.supabase.co:5432/postgres
SUPABASE_URL=https://xxx.supabase.co
SUPABASE_ANON_KEY=<anon-key>
SUPABASE_SERVICE_ROLE_KEY=<service-role-key>
FRONTEND_URL=http://localhost:3002
PORT=3003
ANTHROPIC_API_KEY=<anthropic-api-key> # For AI backtest explanations
CRON_SECRET_TOKEN=<secret-token> # For cron job authenticationFrontend (apps/frontend/.env.local):
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=<anon-key>
NEXT_PUBLIC_API_URL=http://localhost:3003/api# Run both backend and frontend
npm run dev
# Or run separately
npm run dev:backend # Backend on http://localhost:3003
npm run dev:frontend # Frontend on http://localhost:3002- Passwordless Authentication - Magic link login via Supabase
- Portfolio Management - Create and manage leveraged portfolios
- Monthly Contributions - Register DCA contributions with deployment tracking
- Manual Position Updates - Update positions from broker data
- Automated Rebalancing - Sophisticated rebalancing algorithm with:
- Sharpe Ratio optimization (Nelder-Mead)
- Deploy signal evaluation (drawdown, weight deviation, volatility)
- Gradual deployment (configurable factor)
- Portfolio Configuration - Customize strategy parameters:
- Leverage range (min, max, target)
- Target asset weights
- Deploy signal thresholds
- Sharpe optimization parameters
- Recommendations Engine - Actionable recommendations:
- Leverage status alerts (low/high)
- Specific purchase recommendations
- Extra contribution calculations
- Contribution day reminders
- Analytics Dashboard - Comprehensive metrics:
- Equity, Exposure, Leverage tracking
- CAGR, Sharpe Ratio, Volatility
- Maximum Drawdown (Equity & Exposure)
- Underwater Days calculation
- Best/Worst day tracking
- User Profile - Personal information and notification preferences
- Historical Data - Monthly metrics history with pagination
- Interactive Charts - SVG-based equity history visualization
- Historical Backtesting - Configurable backtest simulator with:
- Calendar-based rolling windows (consistent across crypto and traditional assets)
- Sharpe optimization with optional dynamic monthly re-optimization
- P10/P50/P90 percentile results sorted by Sharpe ratio
- Proper margin call handling
- Saved Strategies - Save backtest configurations and results:
- List with P10/P50/P90 metrics
- Trajectory charts visualization
- Create new portfolio from strategy configuration
- AI Analysis - Claude-powered backtest explanations with streaming responses
- Auto-fill Price Gaps - Automatic detection and download of missing historical data
- Email/SMS notifications for urgent alerts
- Broker API integration (webhooks)
- Recommendation history tracking
- Data export (CSV/Excel)
- "What if" simulator before rebalancing
Base URL: http://localhost:3003/api
POST /auth/login- Send magic linkGET /auth/me- Get current user
GET /users/profile- Get user profilePUT /users/profile- Update user profile
GET /portfolios?email=...- List user portfoliosGET /portfolios/:id- Get portfolio detailsGET /portfolios/:id/summary- Get portfolio summary with analyticsGET /portfolios/:id/metrics- Get monthly metrics historyGET /portfolios/:id/daily-metrics- Get daily metrics
GET /portfolios/:portfolioId/configuration- Get portfolio configurationPUT /portfolios/:portfolioId/configuration- Update configurationGET /portfolios/:portfolioId/configuration/target-weights- Get target weightsGET /portfolios/:portfolioId/configuration/is-contribution-day- Check if today is contribution day
GET /portfolios/:portfolioId/recommendations- Get current recommendations
POST /contributions- Register monthly contribution
POST /positions- Update portfolio positions (upsert)GET /positions/search-symbols?q=...- Search asset symbols
GET /portfolios/:portfolioId/rebalance/proposal- Get rebalancing proposalPOST /portfolios/:portfolioId/rebalance/accept- Accept and save rebalancing
GET /strategies- List saved strategiesPOST /strategies- Save new strategyGET /strategies/:id- Get strategy detailPATCH /strategies/:id- Update strategy nameDELETE /strategies/:id- Delete strategyPOST /strategies/:id/create-portfolio- Create portfolio from strategy
GET /backtest/prices- Get historical prices for backtestPOST /backtest/explain- Get AI explanation for backtest results (SSE)
For complete API documentation, see CLAUDE.md (section "API endpoints").
cd infra/scripts
npm run price:ingestFetches daily asset prices from Yahoo Finance and stores in asset_prices table.
Cron: Daily (e.g., 6 AM UTC)
cd infra/scripts
npm run metrics:refreshRecalculates daily metrics for all portfolios and writes to metrics_timeseries and daily_metrics.
Cron: Daily (e.g., 7 AM UTC, after price-ingestion)
cd infra/scripts
npm run daily:checkDaily portfolio verification:
- Calculates current state (equity, exposure, leverage)
- Evaluates deploy signals
- Detects leverage out of range
- Generates recommendations
- Stores daily metrics
Cron: Daily (e.g., 9 AM UTC, after metrics-refresh)
The database schema is defined in apps/backend/prisma/schema.prisma. Main models:
- User - User accounts with notification preferences
- Portfolio - Portfolio configuration and strategy parameters
- Asset - Financial assets (crypto, commodities, indices, etc.)
- PortfolioPosition - Current holdings
- MonthlyContribution - DCA contributions with deployment tracking
- RebalanceEvent - Rebalancing history
- RebalancePosition - Target positions for rebalancing
- AssetPrice - Historical daily prices
- MetricsTimeseries - Monthly portfolio metrics
- DailyMetric - Daily portfolio metrics
See CLAUDE.md (section "Esquema de base de datos") for complete schema documentation.
The rebalancing algorithm replicates the logic from BacktestHistorical.ipynb:
-
Deploy Signal Evaluation:
- Drawdown > 12% โ Full deploy
- Weight deviation > 5% โ Full deploy
- Volatility < 18% โ Full deploy
- Gradual deploy factor (default: 0.5)
-
Weight Optimization:
- Static weights for first 3 months
- Dynamic Sharpe optimization after 3 months (Nelder-Mead)
- 60% shrinkage to mean returns (conservatism)
- Constraints: min 5%, max 40% per asset
-
Target Exposure Calculation:
- Based on target leverage and available equity
- Clamped between min/max leverage bounds
Generates actionable recommendations based on:
- Leverage status: Low (needs reborrow), High (needs extra contribution), In Range
- Deploy signals: Drawdown, weight deviation, volatility
- Contribution days: Reminders for scheduled contributions
/- Login page (passwordless)/dashboard- Main dashboard with metrics, charts, and recommendations/dashboard/contribution- Register monthly contribution/dashboard/manual-update- Update positions manually/dashboard/rebalance- View and accept rebalancing proposals/dashboard/configuration- Configure portfolio strategy/dashboard/backtest- Historical backtest simulator with configurable parameters/dashboard/strategies- List of saved strategies with metrics/dashboard/strategies/[id]- Strategy detail with trajectories and apply to portfolio/dashboard/onboarding- Portfolio creation wizard (SSE progress)/dashboard/profile- User profile and preferences/dashboard/help- Help and documentation
The app uses Supabase passwordless authentication:
- User enters email
- Receives magic link via email
- Clicks link โ redirects to dashboard
- Token stored in
localStorageassupabase_token
Backend verifies tokens by decoding JWT directly (no HTTP calls to Supabase) and searches for users by email in the local database.
The system calculates comprehensive portfolio analytics:
- Equity - Current capital (exposure - borrowed)
- Exposure - Total position value
- Leverage - Effective leverage (exposure / equity)
- CAGR - Compound annual growth rate
- Sharpe Ratio - Risk-adjusted return
- Volatility - Annualized standard deviation
- Maximum Drawdown - Largest drop from peak (Equity & Exposure)
- Underwater Days - Days where equity < total invested
- Best/Worst Day - Days with highest gain/loss
- Notifications: User preferences are stored but no email/SMS delivery is implemented (only logging)
CLAUDE.md- Comprehensive documentation for LLMs (complete project context)apps/backend/prisma/schema.prisma- Database schemaapps/backend/src/- Backend source codeapps/frontend/pages/- Frontend pages
- Platform: Render/Railway (Docker)
- Database: Supabase PostgreSQL
- Cron Jobs: Configure via platform schedulers or Supabase cron
- Platform: Vercel
- Repository:
github.com/clriesco/margn-app - Build: Automatic on push to main branch
# Backend unit tests
npm --workspace apps/backend run test
# Frontend unit tests
npm --workspace apps/frontend run test
# E2E tests
npm --workspace apps/backend run test:e2e# Frontend
http://localhost:3002
# Backend health check
http://localhost:3003/api
# Test login
POST http://localhost:3003/api/auth/login
Body: { "email": "you@example.com" }# Install dependencies
npm install
# Development
npm run dev # Both backend and frontend
npm run dev:backend # Backend only
npm run dev:frontend # Frontend only
# Database
cd apps/backend
npm run prisma:push # Sync schema
npm run prisma:generate # Generate Prisma Client
npm run prisma:studio # Open Prisma Studio
# Build
npm run build # Build all
cd apps/backend && npm run build
cd apps/frontend && npm run build
# Lint
npm run lint- Real equity calculation (track
borrowedAmount) - Auth guard and portfolio ownership validation
- Auto-fetch prices in position updates
- Onboarding wizard with SSE progress
- Backtest simulator with calendar-based rolling windows
- Saved strategies with create portfolio from strategy
- AI-powered backtest explanations
- Cron jobs in production (GitHub Actions)
- Test suite (67 tests: unit, integration, e2e)
- Email/SMS notifications for urgent alerts
- Recommendation history (persist past recommendations)
- Multiple portfolios per user
- Broker API integration
- Data export (CSV/Excel)
Private project - All rights reserved
Last updated: February 2026 Status: Functional MVP with core features implemented