architecture-reference
Scannednpx machina-cli add skill aiskillstore/marketplace/architecture-reference --openclawPortfolio Buddy 2 - Architecture Reference
Component Hierarchy
App.tsx (351 lines)
├── Header
│ └── App title and branding
├── UploadSection
│ ├── File upload to Supabase
│ ├── CSV parsing and validation
│ └── Error handling
├── ErrorList
│ └── Display parsing/validation errors
├── UploadedFilesList
│ └── List of successfully uploaded files
├── AnalyticsControls
│ ├── Toggle Metrics view
│ ├── Toggle Portfolio view
│ └── Toggle Correlation view
├── PortfolioSection (591 lines - NEEDS REFACTOR!)
│ ├── usePortfolio hook (date filtering)
│ ├── useContractMultipliers hook
│ ├── Chart.js equity curves
│ ├── Portfolio statistics
│ ├── ContractInput components
│ ├── MasterContractControl
│ └── MetricsTable integration
├── CorrelationSection
│ ├── CorrelationHeatmap (Chart.js)
│ ├── Spearman correlation
│ └── Pearson correlation
├── MetricsTable (242 lines)
│ ├── useMetrics hook
│ ├── useSorting hook (advanced multi-column)
│ ├── SortableHeader components
│ └── Selection state management
└── SessionComplete
└── Completion UI/messaging
Key Hooks
useMetrics
Location: src/hooks/useMetrics.ts Purpose: Calculate trading metrics from uploaded portfolio data Features:
- Calculates Sharpe Ratio, Sortino Ratio, Max Drawdown, CAGR, Win Rate, etc.
- Memoized calculations for performance
- Handles empty/invalid data gracefully
Usage:
const { metrics, isCalculating } = useMetrics(portfolioData, riskFreeRate)
Returns:
metrics: Array of calculated metrics per strategyisCalculating: Boolean loading state
Note: Contains 4 TypeScript any violations in sort comparisons (tech debt)
usePortfolio
Location: src/hooks/usePortfolio.ts Purpose: Manage portfolio data with date range filtering Features:
- Parses CSV trade data
- Filters by date range (start/end date)
- Builds equity curves
- Aggregates daily returns
Usage:
const {
portfolioData,
filteredData,
dateRange,
setDateRange
} = usePortfolio(uploadedFiles)
Recent Addition: Date range filtering (commit 258ba3a)
Note: Contains 11 TypeScript any violations in trade/metrics types (tech debt)
useContractMultipliers
Location: src/hooks/useContractMultipliers.ts Purpose: Manage contract multipliers for futures trading Features:
- Per-strategy contract size tracking
- Apply multipliers to metrics
- Master control to set all contracts at once
Usage:
const {
multipliers,
setMultiplier,
setAllMultipliers,
getAdjustedMetrics
} = useContractMultipliers(strategies)
useSorting
Location: src/hooks/useSorting.ts Purpose: Advanced multi-column sorting for MetricsTable Features:
- Sort by multiple columns with priority
- Toggle ascending/descending
- Custom comparison logic per data type
Usage:
const {
sortedData,
sortColumn,
sortDirection,
handleSort
} = useSorting(data, defaultColumn)
Utility Functions
dataUtils.ts
Location: src/utils/dataUtils.ts Contains Core Functions:
CSV & Data Processing:
parseCSV(file)- Parse CSV file with PapaParseprocessCurrencyColumns(data)- Clean currency values ($, commas)parseFilenameComponents(filename)- Extract symbol/direction/strategy from filenamegetDisplayName(symbol, direction, strategy)- Format display namesnormalizeDate(date)- Normalize dates to midnight UTCgetDateKey(date)- Convert date to YYYY-MM-DD string key
Metric Calculations:
calculateMetrics(data, filename)- Calculate trade-level metrics for a strategy- Net Profit, Gross Profit/Loss
- Profit Factor, Win Rate
- Average Win/Loss, Expected Value
- Max Drawdown (from equity curve)
- CAGR equivalent (annualGrowthRate)
- Total trades, winning/losing counts
- Note: Does NOT calculate Sharpe or Sortino (those are in PortfolioSection.tsx)
getAdjustedMetrics(metrics, multiplier)- Apply contract multiplier to metrics
Risk-Adjusted Metrics (PortfolioSection.tsx):
- Sharpe Ratio (line 533): Calculated inline as
(annualGrowthRate / 100) / (maxDrawdown / startingCapital) - Sortino Ratio (lines 133-158): Calculated inline with downside deviation, uses risk-free rate state
Correlation Analysis:
buildCorrelationMatrix(strategies)- Build Spearman correlation matrixcalculatePearsonCorrelation(returns1, returns2)- Pearson correlation coefficientcalculateRanks(values)- Rank calculation for Spearman correlation
Trading Calculations:
getMarginRate(symbol)- Get margin requirements by symbolcalculateEquityCurve(trades)- Build cumulative equity curvecalculateDailyReturns(equity)- Calculate daily returns from equity curve
Formatting:
formatNumber(value, decimals)- Format numbers with decimalsformatCurrency(value)- Format as currency ($X,XXX.XX)formatPercent(value)- Format as percentage (X.XX%)
Note: Contains 1 TypeScript any violation in Metrics interface (tech debt)
Data Flow
Upload & Processing Flow
1. User uploads CSV via UploadSection
↓
2. parseCSV() extracts trade data
↓
3. processCurrencyColumns() cleans data
↓
4. File uploaded to Supabase storage
↓
5. usePortfolio hook fetches and aggregates data
↓
6. Date range filter applied (if set)
↓
7. useMetrics calculates all metrics
↓
8. MetricsTable displays results
Contract Multiplier Flow
1. User inputs contract size in ContractInput
↓
2. useContractMultipliers stores value
↓
3. getAdjustedMetrics() applies multiplier
↓
4. Adjusted metrics shown in MetricsTable
↓
5. Portfolio charts update with adjusted values
Sorting Flow
1. User clicks SortableHeader
↓
2. useSorting updates sort column/direction
↓
3. Custom comparison logic applied
↓
4. MetricsTable re-renders with sorted data
Correlation Flow
1. User selects assets in MetricsTable
↓
2. Selection state passed to CorrelationSection
↓
3. buildCorrelationMatrix() calculates correlations
↓
4. CorrelationHeatmap renders Chart.js heatmap
↓
5. Spearman & Pearson correlations both shown
State Management
Plain React Hooks (No Zustand/TanStack Query)
- Local component state →
useState - Derived state →
useMemo - Stable callbacks →
useCallback - Refs for values →
useRef
Example Pattern:
const [data, setData] = useState<Trade[]>([])
const metrics = useMemo(() => calculateMetrics(data), [data])
const handleUpload = useCallback((file: File) => {
// upload logic
}, [])
No Global State Library
- Props passed down component tree
- Custom hooks encapsulate shared logic
- No Redux, Zustand, or Jotai
Adding New Features
New Metric Calculation
- Add calculation logic to
dataUtils.calculateMetrics() - Update return type in
calculateMetrics() - Add column to
MetricsTable.tsx - Update sort logic in
useSorting.tsif needed - Test with sample data
Example: Sortino Ratio was added in commits 258ba3a & 9f25040
New Chart Component
- Create component in
src/components/ - Use Chart.js (NOT Recharts - it's unused)
- Import chart type and plugins needed:
import { Line } from 'react-chartjs-2' import { Chart, registerables } from 'chart.js' import zoomPlugin from 'chartjs-plugin-zoom' - Hook into
useMetricsorusePortfoliofor data - Add to appropriate section in
App.tsx
New Hook
- Create in
src/hooks/use[Feature].ts - Follow naming convention:
useprefix, camelCase - Return object with clear property names
- Use TypeScript for all types (avoid
any) - Add JSDoc comments for complex logic
Chart.js Architecture
Current Setup
- Library: Chart.js 4.x (NOT Recharts)
- React Wrapper: react-chartjs-2
- Plugins Used:
- chartjs-plugin-zoom (pan & zoom)
- chartjs-plugin-annotation (trend lines, markers)
- chartjs-adapter-date-fns (time scales)
Where Charts Are Used
- PortfolioSection: Equity curve line charts
- CorrelationHeatmap: Correlation matrix heatmap
- CustomTooltip: Shared tooltip component for charts
Recharts Note
⚠️ Recharts is installed but NEVER imported - should be removed (11.5KB waste)
Component Size Guidelines
Target: 200 Lines Max
Current Violations:
- ❌ PortfolioSection.tsx: 591 lines (295% of limit) - HIGH PRIORITY REFACTOR
- ❌ App.tsx: 351 lines (175% of limit)
- ❌ MetricsTable.tsx: 242 lines (121% of limit) - improved from 350
Refactoring Strategy
For PortfolioSection (591 lines):
- Extract equity chart into
EquityChartSection.tsx - Extract statistics into
PortfolioStats.tsx - Extract contract controls into
ContractControls.tsx - Keep only orchestration logic in main component
TypeScript Patterns
Interfaces for Data Structures
interface Trade {
date: Date
symbol: string
pnl: number
// ...
}
interface Metric {
name: string
sharpe: number
sortino: number
// ...
}
Avoid any Types
Current violations (15 total) - see portfolio-context skill for details
Preferred approach:
// Bad
const data: any = parseData()
// Good
interface ParsedData {
trades: Trade[]
errors: string[]
}
const data: ParsedData = parseData()
Performance Patterns
Memoization with useMemo
// Expensive correlation calculation
const correlationMatrix = useMemo(
() => buildCorrelationMatrix(selectedStrategies),
[selectedStrategies]
)
Stable Callbacks with useCallback
const handleSort = useCallback((column: string) => {
setSortColumn(column)
setSortDirection(prev => prev === 'asc' ? 'desc' : 'asc')
}, [])
Avoid Premature Optimization
- Build features first
- Profile if performance issues arise
- Optimize based on data, not assumptions
Source
git clone https://github.com/aiskillstore/marketplace/blob/main/skills/5minfutures/architecture-reference/SKILL.mdView on GitHub Overview
Provides a quick reference to the Portfolio Buddy 2 project structure, including the component hierarchy, core hooks, and utilities. It helps developers understand data flow, debug features, and onboard faster.
How This Skill Works
This reference maps each major component to its responsibilities, the key hooks (usePortfolio, useMetrics, useContractMultipliers), and the data utilities that power parsing and normalization. Developers follow these mappings to trace data flow from CSV uploads through portfolio calculations and visualizations.
When to Use It
- When adding new features or modifying components in PortfolioSection or AnalyticsControls
- When debugging data flow from CSV parsing to portfolio metrics and charts
- When onboarding new developers to the codebase
- When planning refactors or reviewing data utilities (dataUtils.ts) and hooks
- When adjusting contract multipliers and their impact on metrics
Quick Start
- Step 1: Review the Component Hierarchy in the Architecture Reference to identify data sources (App.tsx, PortfolioSection, MetricsTable, etc.)
- Step 2: Open the key hooks (src/hooks/usePortfolio.ts, src/hooks/useMetrics.ts, src/hooks/useContractMultipliers.ts) to understand data flow and state
- Step 3: Check dataUtils.ts (src/utils/dataUtils.ts) for CSV parsing, currency cleaning, and date normalization before implementing changes
Best Practices
- Start with the Component Hierarchy to locate data sources and responsibilities
- Use the core hooks (usePortfolio, useMetrics, useContractMultipliers) as the single source of truth for domain data
- Review dataUtils.ts for CSV parsing, currency normalization, and date handling before changes
- Be mindful of tech debt notes: there are TypeScript 'any' violations in useMetrics and usePortfolio
- Reference MetricsTable integration and useSorting for reproducing multi-column sort behavior
Example Use Cases
- Add a new CSV field: update usePortfolio and dataUtils.ts to reflect the new column and rebuild equity curves
- Debug metric calculations by inspecting outputs from useMetrics (Sharpe, Drawdown, CAGR)
- Tune per-strategy contract multipliers with useContractMultipliers to reflect updated risk settings
- Reproduce a multi-column sort in MetricsTable using the useSorting hook
- Onboard a new dev by tracing data flow from UploadSection through PortfolioSection to SessionComplete