Skip to content

Portfolios

Create portfolios, manage positions, and track performance metrics.

MethodEndpointAuthDescription
POST/portfoliosYesCreate portfolio
GET/portfoliosYesList portfolios
GET/portfolios/{id}YesGet portfolio
PUT/portfolios/{id}YesUpdate portfolio
DELETE/portfolios/{id}YesDelete portfolio
POST/portfolios/{id}/cashYesAdjust cash balance
GET/portfolios/{id}/positionsYesGet positions
POST/portfolios/{id}/positionsYesAdd position
PUT/portfolios/{id}/positions/{pos_id}YesUpdate position
DELETE/portfolios/{id}/positions/{pos_id}YesClose position
GET/portfolios/{id}/performanceYesGet performance metrics

POST /api/v1/portfolios
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "Growth Portfolio",
"description": "Long-term tech growth stocks",
"strategy_id": "550e8400-e29b-41d4-a716-446655440000",
"cash_balance": 100000.00,
"is_live": false
}
FieldTypeRequiredDefaultDescription
namestringYes-Portfolio name (1-200 chars)
descriptionstringNo-Portfolio description
strategy_idUUIDNo-Associated strategy
cash_balancedecimalNo100000Initial cash ($)
is_livebooleanNofalsePaper vs live trading

Add a new position to a portfolio.

POST /api/v1/portfolios/990e8400-.../positions
Authorization: Bearer <token>
Content-Type: application/json
{
"symbol": "AAPL",
"quantity": 50,
"avg_price": 185.50
}
FieldTypeDescription
symbolstringStock ticker
quantitydecimalShares (positive=long, negative=short)
avg_pricedecimalAverage entry price
opened_atdatetimePosition open time
current_pricedecimalLatest market price
market_valuedecimalCurrent market value
cost_basisdecimalTotal cost
unrealized_pnldecimalUnrealized profit/loss ($)
unrealized_pnl_pctdecimalUnrealized P&L (%)

Get comprehensive portfolio performance metrics.

GET /api/v1/portfolios/990e8400-.../performance
Authorization: Bearer <token>
MetricDescription
cash_balanceAvailable cash
total_market_valueSum of all position values
total_portfolio_valueCash + market value
total_cost_basisTotal invested amount
total_unrealized_pnlUnrealized profit/loss
total_unrealized_pnl_pctP&L as percentage
open_positions_countActive positions
closed_positions_countClosed positions

Deposit or withdraw cash from a portfolio.

POST /api/v1/portfolios/990e8400-.../cash
Authorization: Bearer <token>
Content-Type: application/json
{
"amount": 5000.00,
"note": "Monthly deposit"
}

Modify an existing position (e.g., add to position).

PUT /api/v1/portfolios/990e8400-.../positions/aa0e8400-...
Authorization: Bearer <token>
Content-Type: application/json
{
"quantity": 75,
"avg_price": 187.50
}

Close a position (marks it as closed, doesn’t delete).

DELETE /api/v1/portfolios/990e8400-.../positions/aa0e8400-...
Authorization: Bearer <token>

const api = axios.create({
baseURL: 'http://localhost:8501/api/v1',
headers: { 'Authorization': `Bearer ${token}` }
});
// Create portfolio
async function createPortfolio(name, initialCash = 100000) {
const { data } = await api.post('/portfolios', {
name,
cash_balance: initialCash,
is_live: false
});
return data;
}
// Add position
async function addPosition(portfolioId, symbol, quantity, price) {
const { data } = await api.post(`/portfolios/${portfolioId}/positions`, {
symbol,
quantity,
avg_price: price
});
return data;
}
// Get portfolio summary
async function getPortfolioSummary(portfolioId) {
const { data } = await api.get(`/portfolios/${portfolioId}/performance`);
console.log(`\n${data.portfolio_name}`);
console.log(`${'='.repeat(40)}`);
console.log(`Cash: $${data.cash_balance.toLocaleString()}`);
console.log(`Positions: $${data.total_market_value.toLocaleString()}`);
console.log(`Total: $${data.total_portfolio_value.toLocaleString()}`);
console.log(`P&L: $${data.total_unrealized_pnl.toLocaleString()} (${data.total_unrealized_pnl_pct.toFixed(2)}%)`);
console.log(`\nPositions:`);
for (const pos of data.positions) {
const pnlSign = pos.unrealized_pnl >= 0 ? '+' : '';
console.log(` ${pos.symbol}: ${pos.quantity} @ $${pos.avg_price} → $${pos.current_price} (${pnlSign}$${pos.unrealized_pnl.toFixed(2)})`);
}
return data;
}
// Usage
const portfolio = await createPortfolio('Tech Growth');
await addPosition(portfolio.id, 'AAPL', 50, 185.50);
await addPosition(portfolio.id, 'MSFT', 25, 420.00);
await getPortfolioSummary(portfolio.id);
import requests
from typing import Optional
from decimal import Decimal
class PortfolioManager:
def __init__(self, base_url: str, token: str):
self.base_url = base_url
self.headers = {"Authorization": f"Bearer {token}"}
def create_portfolio(
self,
name: str,
initial_cash: float = 100000,
description: str = ""
) -> dict:
"""Create a new portfolio."""
response = requests.post(
f"{self.base_url}/portfolios",
headers=self.headers,
json={
"name": name,
"description": description,
"cash_balance": initial_cash,
"is_live": False
}
)
response.raise_for_status()
return response.json()
def add_position(
self,
portfolio_id: str,
symbol: str,
quantity: float,
price: float
) -> dict:
"""Add a position to portfolio."""
response = requests.post(
f"{self.base_url}/portfolios/{portfolio_id}/positions",
headers=self.headers,
json={
"symbol": symbol,
"quantity": quantity,
"avg_price": price
}
)
response.raise_for_status()
return response.json()
def get_performance(self, portfolio_id: str) -> dict:
"""Get portfolio performance metrics."""
response = requests.get(
f"{self.base_url}/portfolios/{portfolio_id}/performance",
headers=self.headers
)
response.raise_for_status()
return response.json()
def adjust_cash(
self,
portfolio_id: str,
amount: float,
note: str = ""
) -> dict:
"""Deposit (positive) or withdraw (negative) cash."""
response = requests.post(
f"{self.base_url}/portfolios/{portfolio_id}/cash",
headers=self.headers,
json={"amount": amount, "note": note}
)
response.raise_for_status()
return response.json()
def print_summary(self, portfolio_id: str):
"""Print portfolio summary."""
perf = self.get_performance(portfolio_id)
print(f"\n{perf['portfolio_name']}")
print("=" * 50)
print(f"Cash: ${perf['cash_balance']:,.2f}")
print(f"Positions: ${perf['total_market_value']:,.2f}")
print(f"Total: ${perf['total_portfolio_value']:,.2f}")
pnl_sign = "+" if perf['total_unrealized_pnl'] >= 0 else ""
print(f"P&L: {pnl_sign}${perf['total_unrealized_pnl']:,.2f} ({pnl_sign}{perf['total_unrealized_pnl_pct']:.2f}%)")
print("\nPositions:")
for pos in perf['positions']:
pnl_sign = "+" if pos['unrealized_pnl'] >= 0 else ""
print(f" {pos['symbol']:6} {pos['quantity']:>6} @ ${pos['avg_price']:.2f} → ${pos['current_price']:.2f} ({pnl_sign}${pos['unrealized_pnl']:.2f})")
# Usage
manager = PortfolioManager("http://localhost:8501/api/v1", token)
# Create portfolio
portfolio = manager.create_portfolio("Tech Growth", 100000)
print(f"Created portfolio: {portfolio['id']}")
# Add positions
manager.add_position(portfolio['id'], "AAPL", 50, 185.50)
manager.add_position(portfolio['id'], "MSFT", 25, 420.00)
manager.add_position(portfolio['id'], "GOOGL", 30, 175.00)
# View summary
manager.print_summary(portfolio['id'])
# Deposit more cash
manager.adjust_cash(portfolio['id'], 5000, "Monthly deposit")

Paper Trading First

Use is_live: false to test strategies before real money.

Track Cost Basis

Always record accurate entry prices for proper P&L tracking.

Regular Reviews

Periodically review portfolio performance and rebalance.

Diversification

Don’t put all capital in one position.