Expand description
§Portfolio Module
This module provides comprehensive portfolio management capabilities for the KiteConnect API v1.0.3, offering both real-time portfolio tracking and detailed analysis of holdings and positions.
§Overview
The portfolio module is the central component for managing your trading and investment portfolio. It provides access to holdings (long-term investments), positions (trading activities), margins, and portfolio analytics with both legacy JSON-based and modern strongly-typed APIs.
§Key Features
§🔄 Dual API Support
- Legacy API: Returns
JsonValue
for backward compatibility - Typed API: Returns structured types with compile-time safety (methods ending in
_typed
)
§📊 Comprehensive Portfolio Data
- Holdings: Long-term investments with P&L tracking
- Positions: Intraday and overnight trading positions
- Margins: Available funds and utilization across segments
- Analytics: Portfolio summaries and performance metrics
§💡 Advanced Features
- Real-time P&L: Live profit/loss calculations
- Position Analysis: Day vs overnight position tracking
- Risk Management: Margin monitoring and limit checking
- Portfolio Conversion: Convert positions between product types
§Available Methods
§Holdings Management
holdings()
/holdings_typed()
- Get all stock holdings- Portfolio analysis and P&L tracking
- T+1 quantity and sellable quantity calculations
§Positions Tracking
positions()
/positions_typed()
- Get current positions- Day and net position separation
- Real-time P&L and M2M calculations
§Margin Management
margins()
/margins_typed()
- Get available margins- Segment-wise margin tracking
- Utilization and available funds monitoring
§Usage Examples
§Holdings Analysis
use kiteconnect_async_wasm::connect::KiteConnect;
let client = KiteConnect::new("api_key", "access_token");
// Get all holdings (typed API - recommended)
let holdings = client.holdings_typed().await?;
let mut total_investment = 0.0;
let mut total_value = 0.0;
let mut total_pnl = 0.0;
println!("Holdings Portfolio Analysis:");
println!("============================");
for holding in &holdings {
let investment = holding.investment_value();
let current_value = holding.market_value();
let pnl_pct = holding.pnl_percentage();
total_investment += investment;
total_value += current_value;
total_pnl += holding.pnl;
println!("📈 {}: {} shares", holding.trading_symbol, holding.quantity);
println!(" 💰 Investment: ₹{:.2} | Current: ₹{:.2}", investment, current_value);
println!(" 📊 P&L: ₹{:.2} ({:.2}%)", holding.pnl, pnl_pct);
// Check trading availability
if holding.can_sell_today() {
println!(" ✅ Can sell {} shares today", holding.sellable_today());
}
println!();
}
let overall_pnl_pct = (total_pnl / total_investment) * 100.0;
println!("🎯 Portfolio Summary:");
println!(" Total Investment: ₹{:.2}", total_investment);
println!(" Current Value: ₹{:.2}", total_value);
println!(" Total P&L: ₹{:.2} ({:.2}%)", total_pnl, overall_pnl_pct);
§Positions Monitoring
use kiteconnect_async_wasm::connect::KiteConnect;
let client = KiteConnect::new("api_key", "access_token");
// Get all positions (typed API)
let positions = client.positions_typed().await?;
println!("Active Trading Positions:");
println!("========================");
let mut day_pnl = 0.0;
let mut total_pnl = 0.0;
for position in &positions {
if !position.is_flat() {
let direction = if position.is_long() { "LONG" } else { "SHORT" };
let pnl_pct = position.pnl_percentage();
day_pnl += position.day_pnl();
total_pnl += position.pnl;
println!("📊 {}: {} {} shares",
position.trading_symbol,
position.abs_quantity(),
direction);
println!(" 💵 Avg: ₹{:.2} | LTP: ₹{:.2}",
position.average_price, position.last_price);
println!(" 📈 P&L: ₹{:.2} ({:.2}%)", position.pnl, pnl_pct);
if position.is_day_position() {
println!(" 🔄 Intraday position");
} else if position.is_overnight_position() {
println!(" 🌙 Overnight position ({})", position.overnight_quantity);
}
println!();
}
}
println!("📊 Trading Summary:");
println!(" Day P&L: ₹{:.2}", day_pnl);
println!(" Total P&L: ₹{:.2}", total_pnl);
§Margin Analysis
use kiteconnect_async_wasm::connect::KiteConnect;
use kiteconnect_async_wasm::models::auth::TradingSegment;
let client = KiteConnect::new("api_key", "access_token");
// Get margin data (typed API)
let margins = client.margins_typed(None).await?;
println!("Margin Analysis:");
println!("===============");
if let Some(ref equity_margin) = margins.equity {
let available = equity_margin.available.cash;
let net = equity_margin.net;
let utilisation_pct = equity_margin.utilisation_percentage();
println!("💰 Equity Segment:");
println!(" Available Cash: ₹{:.2}", available);
println!(" Net Margin: ₹{:.2}", net);
println!(" Utilisation: {:.1}%", utilisation_pct);
// Check if sufficient margin for trading
let required_margin = 50000.0; // Example
if equity_margin.can_place_order(required_margin) {
println!(" ✅ Sufficient margin for ₹{:.0} order", required_margin);
} else {
println!(" ❌ Insufficient margin for ₹{:.0} order", required_margin);
}
}
if let Some(ref commodity_margin) = margins.commodity {
println!("🌾 Commodity Segment:");
println!(" Available Cash: ₹{:.2}", commodity_margin.available.cash);
println!(" Net Margin: ₹{:.2}", commodity_margin.net);
}
// Overall margin check
let total_cash = margins.total_cash();
let total_net = margins.total_net_margin();
println!("🎯 Total Available: ₹{:.2} | Net: ₹{:.2}", total_cash, total_net);
§Portfolio Risk Analysis
use kiteconnect_async_wasm::connect::KiteConnect;
let client = KiteConnect::new("api_key", "access_token");
// Get holdings and positions for comprehensive analysis
let (holdings, positions) = tokio::try_join!(
client.holdings_typed(),
client.positions_typed()
)?;
println!("Portfolio Risk Analysis:");
println!("=======================");
// Holdings analysis
let profitable_holdings = holdings.iter().filter(|h| h.is_profitable()).count();
let loss_holdings = holdings.iter().filter(|h| h.is_loss()).count();
let holdings_win_rate = (profitable_holdings as f64 / holdings.len() as f64) * 100.0;
println!("📊 Holdings (Long-term):");
println!(" Total Holdings: {}", holdings.len());
println!(" Profitable: {} | Loss-making: {}", profitable_holdings, loss_holdings);
println!(" Win Rate: {:.1}%", holdings_win_rate);
// Positions analysis
let active_positions: Vec<_> = positions.iter().filter(|p| !p.is_flat()).collect();
let profitable_positions = active_positions.iter().filter(|p| p.is_profitable()).count();
let loss_positions = active_positions.iter().filter(|p| p.is_loss()).count();
if !active_positions.is_empty() {
let positions_win_rate = (profitable_positions as f64 / active_positions.len() as f64) * 100.0;
println!("📈 Active Positions (Trading):");
println!(" Active Positions: {}", active_positions.len());
println!(" Profitable: {} | Loss-making: {}", profitable_positions, loss_positions);
println!(" Win Rate: {:.1}%", positions_win_rate);
}
// Risk metrics
let total_holdings_value: f64 = holdings.iter().map(|h| h.market_value()).sum();
let total_position_exposure: f64 = active_positions.iter()
.map(|p| p.market_value())
.sum();
println!("⚖️ Risk Exposure:");
println!(" Holdings Value: ₹{:.2}", total_holdings_value);
println!(" Position Exposure: ₹{:.2}", total_position_exposure);
println!(" Total Exposure: ₹{:.2}", total_holdings_value + total_position_exposure);
§Data Models
§Holdings
The Holding
struct represents long-term investments with comprehensive tracking:
- Investment tracking: Average price, current price, P&L calculations
- Quantity management: Total, T+1, realised, and pledged quantities
- Trading availability: Check what can be sold today vs tomorrow
- Portfolio analytics: Market value, investment value, percentage returns
§Positions
The Position
struct represents active trading positions:
- Direction tracking: Long vs short positions
- Day vs Net: Separate intraday and overnight positions
- P&L breakdown: Realised, unrealised, and M2M calculations
- Risk metrics: Exposure, margin requirements
§Margins
The MarginData
struct provides fund information:
- Segment-wise: Equity and commodity margins separately
- Available funds: Cash, collateral, and total available
- Utilisation: Used margin and exposure tracking
- Order capacity: Check if sufficient margin for new orders
§Error Handling
All methods return Result<T>
with comprehensive error information:
use kiteconnect_async_wasm::models::common::KiteError;
match client.holdings_typed().await {
Ok(holdings) => {
println!("Portfolio loaded: {} holdings", holdings.len());
// Process holdings...
}
Err(KiteError::Authentication(msg)) => {
eprintln!("Authentication failed: {}", msg);
// Handle re-authentication
}
Err(KiteError::Api { status, message, .. }) => {
eprintln!("API Error {}: {}", status, message);
// Handle API errors
}
Err(e) => eprintln!("Other error: {}", e),
}
§Performance Considerations
§Efficient Data Access
- Batch Operations: Get holdings and positions together with
tokio::try_join!
- Typed APIs: Use
*_typed()
methods for better performance and type safety - Selective Updates: Update only necessary data for real-time monitoring
§Memory Usage
- Structured Data: Typed APIs use less memory than JSON parsing
- Efficient Calculations: Built-in helper methods reduce computation overhead
- Lazy Evaluation: Calculate metrics only when needed
§Rate Limiting
The module automatically handles rate limiting according to KiteConnect API guidelines:
- Portfolio APIs: 3 requests per second for holdings, positions, margins
- Automatic Retry: Built-in retry mechanism with exponential backoff
- Connection Pooling: HTTP connections are reused for better performance
§Thread Safety
All methods are thread-safe and can be called concurrently:
// Concurrent portfolio data retrieval
let (holdings, positions, margins) = tokio::try_join!(
client.holdings_typed(),
client.positions_typed(),
client.margins_typed(None)
)?;
// All data retrieved concurrently for maximum efficiency
§Migration from v1.0.2
All existing methods continue to work. New typed methods provide enhanced features:
- Replace
holdings()
withholdings_typed()
for structured data - Use
positions_typed()
andmargins_typed()
for type safety - Legacy methods remain available for backward compatibility
- Enhanced helper methods on all model structs for better analytics