[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6EJ05PS9DZPPCS212KB6RVG":3,"skill-same:01M6EJ05PS9DZPPCS212KB6RVG":82},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":41,"linkOnly":42,"markdownContent":43,"markdownBody":44,"frontMatter":45,"refName":46,"commitSha":47,"skillDirectory":48,"forksCount":49,"repositoryHtmlUrl":50,"repositoryHomepageUrl":51,"ownerHtmlUrl":52,"ownerBlogUrl":6,"ownerDescription":53,"updatedAt":54,"install":55,"resources":68},"01M6EJ05PS9DZPPCS212KB6RVG","architecture-reference",null,"Quick reference for Portfolio Buddy 2 project structure. Use when: adding new features, modifying existing components, understanding data flow, or onboarding to the codebase. Contains component hierarchy, hook patterns, and utility functions.","ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",66,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002F5minfutures\u002Farchitecture-reference\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000033","数据分析师","PROFESSION","适用职业",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40],"architecture reference","architecture","reference","use","utility","project","structure","patterns","functions","portfolio","components","data","flow","onboarding","quick reference","project structure","component","2026-11-10 10:12:30",false,"---\nname: architecture-reference\ndescription: \"Quick reference for Portfolio Buddy 2 project structure. Use when: adding new features, modifying existing components, understanding data flow, or onboarding to the codebase. Contains component hierarchy, hook patterns, and utility functions.\"\n---\n\n# Portfolio Buddy 2 - Architecture Reference\n\n## Component Hierarchy\n\n```\nApp.tsx (351 lines)\n├── Header\n│   └── App title and branding\n├── UploadSection\n│   ├── File upload to Supabase\n│   ├── CSV parsing and validation\n│   └── Error handling\n├── ErrorList\n│   └── Display parsing\u002Fvalidation errors\n├── UploadedFilesList\n│   └── List of successfully uploaded files\n├── AnalyticsControls\n│   ├── Toggle Metrics view\n│   ├── Toggle Portfolio view\n│   └── Toggle Correlation view\n├── PortfolioSection (591 lines - NEEDS REFACTOR!)\n│   ├── usePortfolio hook (date filtering)\n│   ├── useContractMultipliers hook\n│   ├── Chart.js equity curves\n│   ├── Portfolio statistics\n│   ├── ContractInput components\n│   ├── MasterContractControl\n│   └── MetricsTable integration\n├── CorrelationSection\n│   ├── CorrelationHeatmap (Chart.js)\n│   ├── Spearman correlation\n│   └── Pearson correlation\n├── MetricsTable (242 lines)\n│   ├── useMetrics hook\n│   ├── useSorting hook (advanced multi-column)\n│   ├── SortableHeader components\n│   └── Selection state management\n└── SessionComplete\n    └── Completion UI\u002Fmessaging\n```\n\n## Key Hooks\n\n### useMetrics\n**Location**: [src\u002Fhooks\u002FuseMetrics.ts](src\u002Fhooks\u002FuseMetrics.ts)\n**Purpose**: Calculate trading metrics from uploaded portfolio data\n**Features**:\n- Calculates Sharpe Ratio, Sortino Ratio, Max Drawdown, CAGR, Win Rate, etc.\n- Memoized calculations for performance\n- Handles empty\u002Finvalid data gracefully\n\n**Usage**:\n```typescript\nconst { metrics, isCalculating } = useMetrics(portfolioData, riskFreeRate)\n```\n\n**Returns**:\n- `metrics`: Array of calculated metrics per strategy\n- `isCalculating`: Boolean loading state\n\n**Note**: Contains 4 TypeScript `any` violations in sort comparisons (tech debt)\n\n### usePortfolio\n**Location**: [src\u002Fhooks\u002FusePortfolio.ts](src\u002Fhooks\u002FusePortfolio.ts)\n**Purpose**: Manage portfolio data with date range filtering\n**Features**:\n- Parses CSV trade data\n- Filters by date range (start\u002Fend date)\n- Builds equity curves\n- Aggregates daily returns\n\n**Usage**:\n```typescript\nconst {\n  portfolioData,\n  filteredData,\n  dateRange,\n  setDateRange\n} = usePortfolio(uploadedFiles)\n```\n\n**Recent Addition**: Date range filtering (commit 258ba3a)\n\n**Note**: Contains 11 TypeScript `any` violations in trade\u002Fmetrics types (tech debt)\n\n### useContractMultipliers\n**Location**: [src\u002Fhooks\u002FuseContractMultipliers.ts](src\u002Fhooks\u002FuseContractMultipliers.ts)\n**Purpose**: Manage contract multipliers for futures trading\n**Features**:\n- Per-strategy contract size tracking\n- Apply multipliers to metrics\n- Master control to set all contracts at once\n\n**Usage**:\n```typescript\nconst {\n  multipliers,\n  setMultiplier,\n  setAllMultipliers,\n  getAdjustedMetrics\n} = useContractMultipliers(strategies)\n```\n\n### useSorting\n**Location**: [src\u002Fhooks\u002FuseSorting.ts](src\u002Fhooks\u002FuseSorting.ts)\n**Purpose**: Advanced multi-column sorting for MetricsTable\n**Features**:\n- Sort by multiple columns with priority\n- Toggle ascending\u002Fdescending\n- Custom comparison logic per data type\n\n**Usage**:\n```typescript\nconst {\n  sortedData,\n  sortColumn,\n  sortDirection,\n  handleSort\n} = useSorting(data, defaultColumn)\n```\n\n## Utility Functions\n\n### dataUtils.ts\n**Location**: [src\u002Futils\u002FdataUtils.ts](src\u002Futils\u002FdataUtils.ts)\n**Contains Core Functions**:\n\n**CSV & Data Processing**:\n- `parseCSV(file)` - Parse CSV file with PapaParse\n- `processCurrencyColumns(data)` - Clean currency values ($, commas)\n- `parseFilenameComponents(filename)` - Extract symbol\u002Fdirection\u002Fstrategy from filename\n- `getDisplayName(symbol, direction, strategy)` - Format display names\n- `normalizeDate(date)` - Normalize dates to midnight UTC\n- `getDateKey(date)` - Convert date to YYYY-MM-DD string key\n\n**Metric Calculations**:\n- `calculateMetrics(data, filename)` - Calculate trade-level metrics for a strategy\n  - Net Profit, Gross Profit\u002FLoss\n  - Profit Factor, Win Rate\n  - Average Win\u002FLoss, Expected Value\n  - Max Drawdown (from equity curve)\n  - CAGR equivalent (annualGrowthRate)\n  - Total trades, winning\u002Flosing counts\n  - **Note**: Does NOT calculate Sharpe or Sortino (those are in PortfolioSection.tsx)\n- `getAdjustedMetrics(metrics, multiplier)` - Apply contract multiplier to metrics\n\n**Risk-Adjusted Metrics** (PortfolioSection.tsx):\n- **Sharpe Ratio** (line 533): Calculated inline as `(annualGrowthRate \u002F 100) \u002F (maxDrawdown \u002F startingCapital)`\n- **Sortino Ratio** (lines 133-158): Calculated inline with downside deviation, uses risk-free rate state\n\n**Correlation Analysis**:\n- `buildCorrelationMatrix(strategies)` - Build Spearman correlation matrix\n- `calculatePearsonCorrelation(returns1, returns2)` - Pearson correlation coefficient\n- `calculateRanks(values)` - Rank calculation for Spearman correlation\n\n**Trading Calculations**:\n- `getMarginRate(symbol)` - Get margin requirements by symbol\n- `calculateEquityCurve(trades)` - Build cumulative equity curve\n- `calculateDailyReturns(equity)` - Calculate daily returns from equity curve\n\n**Formatting**:\n- `formatNumber(value, decimals)` - Format numbers with decimals\n- `formatCurrency(value)` - Format as currency ($X,XXX.XX)\n- `formatPercent(value)` - Format as percentage (X.XX%)\n\n**Note**: Contains 1 TypeScript `any` violation in Metrics interface (tech debt)\n\n## Data Flow\n\n### Upload & Processing Flow\n```\n1. User uploads CSV via UploadSection\n   ↓\n2. parseCSV() extracts trade data\n   ↓\n3. processCurrencyColumns() cleans data\n   ↓\n4. File uploaded to Supabase storage\n   ↓\n5. usePortfolio hook fetches and aggregates data\n   ↓\n6. Date range filter applied (if set)\n   ↓\n7. useMetrics calculates all metrics\n   ↓\n8. MetricsTable displays results\n```\n\n### Contract Multiplier Flow\n```\n1. User inputs contract size in ContractInput\n   ↓\n2. useContractMultipliers stores value\n   ↓\n3. getAdjustedMetrics() applies multiplier\n   ↓\n4. Adjusted metrics shown in MetricsTable\n   ↓\n5. Portfolio charts update with adjusted values\n```\n\n### Sorting Flow\n```\n1. User clicks SortableHeader\n   ↓\n2. useSorting updates sort column\u002Fdirection\n   ↓\n3. Custom comparison logic applied\n   ↓\n4. MetricsTable re-renders with sorted data\n```\n\n### Correlation Flow\n```\n1. User selects assets in MetricsTable\n   ↓\n2. Selection state passed to CorrelationSection\n   ↓\n3. buildCorrelationMatrix() calculates correlations\n   ↓\n4. CorrelationHeatmap renders Chart.js heatmap\n   ↓\n5. Spearman & Pearson correlations both shown\n```\n\n## State Management\n\n### Plain React Hooks (No Zustand\u002FTanStack Query)\n- **Local component state** → `useState`\n- **Derived state** → `useMemo`\n- **Stable callbacks** → `useCallback`\n- **Refs for values** → `useRef`\n\n**Example Pattern**:\n```typescript\nconst [data, setData] = useState\u003CTrade[]>([])\nconst metrics = useMemo(() => calculateMetrics(data), [data])\nconst handleUpload = useCallback((file: File) => {\n  \u002F\u002F upload logic\n}, [])\n```\n\n### No Global State Library\n- Props passed down component tree\n- Custom hooks encapsulate shared logic\n- No Redux, Zustand, or Jotai\n\n## Adding New Features\n\n### New Metric Calculation\n1. Add calculation logic to `dataUtils.calculateMetrics()`\n2. Update return type in `calculateMetrics()`\n3. Add column to `MetricsTable.tsx`\n4. Update sort logic in `useSorting.ts` if needed\n5. Test with sample data\n\n**Example**: Sortino Ratio was added in commits 258ba3a & 9f25040\n\n### New Chart Component\n1. Create component in `src\u002Fcomponents\u002F`\n2. Use Chart.js (NOT Recharts - it's unused)\n3. Import chart type and plugins needed:\n   ```typescript\n   import { Line } from 'react-chartjs-2'\n   import { Chart, registerables } from 'chart.js'\n   import zoomPlugin from 'chartjs-plugin-zoom'\n   ```\n4. Hook into `useMetrics` or `usePortfolio` for data\n5. Add to appropriate section in `App.tsx`\n\n### New Hook\n1. Create in `src\u002Fhooks\u002Fuse[Feature].ts`\n2. Follow naming convention: `use` prefix, camelCase\n3. Return object with clear property names\n4. Use TypeScript for all types (avoid `any`)\n5. Add JSDoc comments for complex logic\n\n## Chart.js Architecture\n\n### Current Setup\n- **Library**: Chart.js 4.x (NOT Recharts)\n- **React Wrapper**: react-chartjs-2\n- **Plugins Used**:\n  - chartjs-plugin-zoom (pan & zoom)\n  - chartjs-plugin-annotation (trend lines, markers)\n  - chartjs-adapter-date-fns (time scales)\n\n### Where Charts Are Used\n1. **PortfolioSection**: Equity curve line charts\n2. **CorrelationHeatmap**: Correlation matrix heatmap\n3. **CustomTooltip**: Shared tooltip component for charts\n\n### Recharts Note\n⚠️ **Recharts is installed but NEVER imported** - should be removed (11.5KB waste)\n\n## Component Size Guidelines\n\n### Target: 200 Lines Max\n**Current Violations**:\n- ❌ PortfolioSection.tsx: 591 lines (295% of limit) - **HIGH PRIORITY REFACTOR**\n- ❌ App.tsx: 351 lines (175% of limit)\n- ❌ MetricsTable.tsx: 242 lines (121% of limit) - improved from 350\n\n### Refactoring Strategy\n**For PortfolioSection (591 lines)**:\n1. Extract equity chart into `EquityChartSection.tsx`\n2. Extract statistics into `PortfolioStats.tsx`\n3. Extract contract controls into `ContractControls.tsx`\n4. Keep only orchestration logic in main component\n\n## TypeScript Patterns\n\n### Interfaces for Data Structures\n```typescript\ninterface Trade {\n  date: Date\n  symbol: string\n  pnl: number\n  \u002F\u002F ...\n}\n\ninterface Metric {\n  name: string\n  sharpe: number\n  sortino: number\n  \u002F\u002F ...\n}\n```\n\n### Avoid `any` Types\n**Current violations (15 total)** - see portfolio-context skill for details\n\n**Preferred approach**:\n```typescript\n\u002F\u002F Bad\nconst data: any = parseData()\n\n\u002F\u002F Good\ninterface ParsedData {\n  trades: Trade[]\n  errors: string[]\n}\nconst data: ParsedData = parseData()\n```\n\n## Performance Patterns\n\n### Memoization with useMemo\n```typescript\n\u002F\u002F Expensive correlation calculation\nconst correlationMatrix = useMemo(\n  () => buildCorrelationMatrix(selectedStrategies),\n  [selectedStrategies]\n)\n```\n\n### Stable Callbacks with useCallback\n```typescript\nconst handleSort = useCallback((column: string) => {\n  setSortColumn(column)\n  setSortDirection(prev => prev === 'asc' ? 'desc' : 'asc')\n}, [])\n```\n\n### Avoid Premature Optimization\n- Build features first\n- Profile if performance issues arise\n- Optimize based on data, not assumptions","# Portfolio Buddy 2 - Architecture Reference\n\n## Component Hierarchy\n\n```\nApp.tsx (351 lines)\n├── Header\n│   └── App title and branding\n├── UploadSection\n│   ├── File upload to Supabase\n│   ├── CSV parsing and validation\n│   └── Error handling\n├── ErrorList\n│   └── Display parsing\u002Fvalidation errors\n├── UploadedFilesList\n│   └── List of successfully uploaded files\n├── AnalyticsControls\n│   ├── Toggle Metrics view\n│   ├── Toggle Portfolio view\n│   └── Toggle Correlation view\n├── PortfolioSection (591 lines - NEEDS REFACTOR!)\n│   ├── usePortfolio hook (date filtering)\n│   ├── useContractMultipliers hook\n│   ├── Chart.js equity curves\n│   ├── Portfolio statistics\n│   ├── ContractInput components\n│   ├── MasterContractControl\n│   └── MetricsTable integration\n├── CorrelationSection\n│   ├── CorrelationHeatmap (Chart.js)\n│   ├── Spearman correlation\n│   └── Pearson correlation\n├── MetricsTable (242 lines)\n│   ├── useMetrics hook\n│   ├── useSorting hook (advanced multi-column)\n│   ├── SortableHeader components\n│   └── Selection state management\n└── SessionComplete\n    └── Completion UI\u002Fmessaging\n```\n\n## Key Hooks\n\n### useMetrics\n**Location**: [src\u002Fhooks\u002FuseMetrics.ts](src\u002Fhooks\u002FuseMetrics.ts)\n**Purpose**: Calculate trading metrics from uploaded portfolio data\n**Features**:\n- Calculates Sharpe Ratio, Sortino Ratio, Max Drawdown, CAGR, Win Rate, etc.\n- Memoized calculations for performance\n- Handles empty\u002Finvalid data gracefully\n\n**Usage**:\n```typescript\nconst { metrics, isCalculating } = useMetrics(portfolioData, riskFreeRate)\n```\n\n**Returns**:\n- `metrics`: Array of calculated metrics per strategy\n- `isCalculating`: Boolean loading state\n\n**Note**: Contains 4 TypeScript `any` violations in sort comparisons (tech debt)\n\n### usePortfolio\n**Location**: [src\u002Fhooks\u002FusePortfolio.ts](src\u002Fhooks\u002FusePortfolio.ts)\n**Purpose**: Manage portfolio data with date range filtering\n**Features**:\n- Parses CSV trade data\n- Filters by date range (start\u002Fend date)\n- Builds equity curves\n- Aggregates daily returns\n\n**Usage**:\n```typescript\nconst {\n  portfolioData,\n  filteredData,\n  dateRange,\n  setDateRange\n} = usePortfolio(uploadedFiles)\n```\n\n**Recent Addition**: Date range filtering (commit 258ba3a)\n\n**Note**: Contains 11 TypeScript `any` violations in trade\u002Fmetrics types (tech debt)\n\n### useContractMultipliers\n**Location**: [src\u002Fhooks\u002FuseContractMultipliers.ts](src\u002Fhooks\u002FuseContractMultipliers.ts)\n**Purpose**: Manage contract multipliers for futures trading\n**Features**:\n- Per-strategy contract size tracking\n- Apply multipliers to metrics\n- Master control to set all contracts at once\n\n**Usage**:\n```typescript\nconst {\n  multipliers,\n  setMultiplier,\n  setAllMultipliers,\n  getAdjustedMetrics\n} = useContractMultipliers(strategies)\n```\n\n### useSorting\n**Location**: [src\u002Fhooks\u002FuseSorting.ts](src\u002Fhooks\u002FuseSorting.ts)\n**Purpose**: Advanced multi-column sorting for MetricsTable\n**Features**:\n- Sort by multiple columns with priority\n- Toggle ascending\u002Fdescending\n- Custom comparison logic per data type\n\n**Usage**:\n```typescript\nconst {\n  sortedData,\n  sortColumn,\n  sortDirection,\n  handleSort\n} = useSorting(data, defaultColumn)\n```\n\n## Utility Functions\n\n### dataUtils.ts\n**Location**: [src\u002Futils\u002FdataUtils.ts](src\u002Futils\u002FdataUtils.ts)\n**Contains Core Functions**:\n\n**CSV & Data Processing**:\n- `parseCSV(file)` - Parse CSV file with PapaParse\n- `processCurrencyColumns(data)` - Clean currency values ($, commas)\n- `parseFilenameComponents(filename)` - Extract symbol\u002Fdirection\u002Fstrategy from filename\n- `getDisplayName(symbol, direction, strategy)` - Format display names\n- `normalizeDate(date)` - Normalize dates to midnight UTC\n- `getDateKey(date)` - Convert date to YYYY-MM-DD string key\n\n**Metric Calculations**:\n- `calculateMetrics(data, filename)` - Calculate trade-level metrics for a strategy\n  - Net Profit, Gross Profit\u002FLoss\n  - Profit Factor, Win Rate\n  - Average Win\u002FLoss, Expected Value\n  - Max Drawdown (from equity curve)\n  - CAGR equivalent (annualGrowthRate)\n  - Total trades, winning\u002Flosing counts\n  - **Note**: Does NOT calculate Sharpe or Sortino (those are in PortfolioSection.tsx)\n- `getAdjustedMetrics(metrics, multiplier)` - Apply contract multiplier to metrics\n\n**Risk-Adjusted Metrics** (PortfolioSection.tsx):\n- **Sharpe Ratio** (line 533): Calculated inline as `(annualGrowthRate \u002F 100) \u002F (maxDrawdown \u002F startingCapital)`\n- **Sortino Ratio** (lines 133-158): Calculated inline with downside deviation, uses risk-free rate state\n\n**Correlation Analysis**:\n- `buildCorrelationMatrix(strategies)` - Build Spearman correlation matrix\n- `calculatePearsonCorrelation(returns1, returns2)` - Pearson correlation coefficient\n- `calculateRanks(values)` - Rank calculation for Spearman correlation\n\n**Trading Calculations**:\n- `getMarginRate(symbol)` - Get margin requirements by symbol\n- `calculateEquityCurve(trades)` - Build cumulative equity curve\n- `calculateDailyReturns(equity)` - Calculate daily returns from equity curve\n\n**Formatting**:\n- `formatNumber(value, decimals)` - Format numbers with decimals\n- `formatCurrency(value)` - Format as currency ($X,XXX.XX)\n- `formatPercent(value)` - Format as percentage (X.XX%)\n\n**Note**: Contains 1 TypeScript `any` violation in Metrics interface (tech debt)\n\n## Data Flow\n\n### Upload & Processing Flow\n```\n1. User uploads CSV via UploadSection\n   ↓\n2. parseCSV() extracts trade data\n   ↓\n3. processCurrencyColumns() cleans data\n   ↓\n4. File uploaded to Supabase storage\n   ↓\n5. usePortfolio hook fetches and aggregates data\n   ↓\n6. Date range filter applied (if set)\n   ↓\n7. useMetrics calculates all metrics\n   ↓\n8. MetricsTable displays results\n```\n\n### Contract Multiplier Flow\n```\n1. User inputs contract size in ContractInput\n   ↓\n2. useContractMultipliers stores value\n   ↓\n3. getAdjustedMetrics() applies multiplier\n   ↓\n4. Adjusted metrics shown in MetricsTable\n   ↓\n5. Portfolio charts update with adjusted values\n```\n\n### Sorting Flow\n```\n1. User clicks SortableHeader\n   ↓\n2. useSorting updates sort column\u002Fdirection\n   ↓\n3. Custom comparison logic applied\n   ↓\n4. MetricsTable re-renders with sorted data\n```\n\n### Correlation Flow\n```\n1. User selects assets in MetricsTable\n   ↓\n2. Selection state passed to CorrelationSection\n   ↓\n3. buildCorrelationMatrix() calculates correlations\n   ↓\n4. CorrelationHeatmap renders Chart.js heatmap\n   ↓\n5. Spearman & Pearson correlations both shown\n```\n\n## State Management\n\n### Plain React Hooks (No Zustand\u002FTanStack Query)\n- **Local component state** → `useState`\n- **Derived state** → `useMemo`\n- **Stable callbacks** → `useCallback`\n- **Refs for values** → `useRef`\n\n**Example Pattern**:\n```typescript\nconst [data, setData] = useState\u003CTrade[]>([])\nconst metrics = useMemo(() => calculateMetrics(data), [data])\nconst handleUpload = useCallback((file: File) => {\n  \u002F\u002F upload logic\n}, [])\n```\n\n### No Global State Library\n- Props passed down component tree\n- Custom hooks encapsulate shared logic\n- No Redux, Zustand, or Jotai\n\n## Adding New Features\n\n### New Metric Calculation\n1. Add calculation logic to `dataUtils.calculateMetrics()`\n2. Update return type in `calculateMetrics()`\n3. Add column to `MetricsTable.tsx`\n4. Update sort logic in `useSorting.ts` if needed\n5. Test with sample data\n\n**Example**: Sortino Ratio was added in commits 258ba3a & 9f25040\n\n### New Chart Component\n1. Create component in `src\u002Fcomponents\u002F`\n2. Use Chart.js (NOT Recharts - it's unused)\n3. Import chart type and plugins needed:\n   ```typescript\n   import { Line } from 'react-chartjs-2'\n   import { Chart, registerables } from 'chart.js'\n   import zoomPlugin from 'chartjs-plugin-zoom'\n   ```\n4. Hook into `useMetrics` or `usePortfolio` for data\n5. Add to appropriate section in `App.tsx`\n\n### New Hook\n1. Create in `src\u002Fhooks\u002Fuse[Feature].ts`\n2. Follow naming convention: `use` prefix, camelCase\n3. Return object with clear property names\n4. Use TypeScript for all types (avoid `any`)\n5. Add JSDoc comments for complex logic\n\n## Chart.js Architecture\n\n### Current Setup\n- **Library**: Chart.js 4.x (NOT Recharts)\n- **React Wrapper**: react-chartjs-2\n- **Plugins Used**:\n  - chartjs-plugin-zoom (pan & zoom)\n  - chartjs-plugin-annotation (trend lines, markers)\n  - chartjs-adapter-date-fns (time scales)\n\n### Where Charts Are Used\n1. **PortfolioSection**: Equity curve line charts\n2. **CorrelationHeatmap**: Correlation matrix heatmap\n3. **CustomTooltip**: Shared tooltip component for charts\n\n### Recharts Note\n⚠️ **Recharts is installed but NEVER imported** - should be removed (11.5KB waste)\n\n## Component Size Guidelines\n\n### Target: 200 Lines Max\n**Current Violations**:\n- ❌ PortfolioSection.tsx: 591 lines (295% of limit) - **HIGH PRIORITY REFACTOR**\n- ❌ App.tsx: 351 lines (175% of limit)\n- ❌ MetricsTable.tsx: 242 lines (121% of limit) - improved from 350\n\n### Refactoring Strategy\n**For PortfolioSection (591 lines)**:\n1. Extract equity chart into `EquityChartSection.tsx`\n2. Extract statistics into `PortfolioStats.tsx`\n3. Extract contract controls into `ContractControls.tsx`\n4. Keep only orchestration logic in main component\n\n## TypeScript Patterns\n\n### Interfaces for Data Structures\n```typescript\ninterface Trade {\n  date: Date\n  symbol: string\n  pnl: number\n  \u002F\u002F ...\n}\n\ninterface Metric {\n  name: string\n  sharpe: number\n  sortino: number\n  \u002F\u002F ...\n}\n```\n\n### Avoid `any` Types\n**Current violations (15 total)** - see portfolio-context skill for details\n\n**Preferred approach**:\n```typescript\n\u002F\u002F Bad\nconst data: any = parseData()\n\n\u002F\u002F Good\ninterface ParsedData {\n  trades: Trade[]\n  errors: string[]\n}\nconst data: ParsedData = parseData()\n```\n\n## Performance Patterns\n\n### Memoization with useMemo\n```typescript\n\u002F\u002F Expensive correlation calculation\nconst correlationMatrix = useMemo(\n  () => buildCorrelationMatrix(selectedStrategies),\n  [selectedStrategies]\n)\n```\n\n### Stable Callbacks with useCallback\n```typescript\nconst handleSort = useCallback((column: string) => {\n  setSortColumn(column)\n  setSortDirection(prev => prev === 'asc' ? 'desc' : 'asc')\n}, [])\n```\n\n### Avoid Premature Optimization\n- Build features first\n- Profile if performance issues arise\n- Optimize based on data, not assumptions",{"name":5,"description":7},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Faiskillstore\u002Fmarketplace\u002F5minfutures\u002Farchitecture-reference",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":8,"skillName":5,"commands":56,"prompt":66,"zipAvailable":67},[57,60,63],{"tool":58,"command":59},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill architecture-reference",{"tool":61,"command":62},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill architecture-reference",{"tool":64,"command":65},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill architecture-reference","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002F5minfutures\u002Farchitecture-reference\u002FSKILL.md",true,[69,75,78],{"path":70,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":73,"sourceHtmlUrl":74},"codex\u002Fprompt.md","REFERENCE","参考文档",207,"https:\u002F\u002Fgithub.com\u002Fberlinguyinca\u002Fautospec\u002Fblob\u002Fmain\u002Fcrates\u002Fautospec-cli\u002Ftests\u002Ffixtures\u002Fvalidation-cutover\u002Fphase4-final-quality\u002Fskills\u002Fautospec-run\u002Fcodex\u002Fprompt.md",{"path":76,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":73,"sourceHtmlUrl":77},"opencode\u002Fagent.md","https:\u002F\u002Fgithub.com\u002Fberlinguyinca\u002Fautospec\u002Fblob\u002Fmain\u002Fcrates\u002Fautospec-cli\u002Ftests\u002Ffixtures\u002Fvalidation-cutover\u002Fphase4-final-quality\u002Fskills\u002Fautospec-run\u002Fopencode\u002Fagent.md",{"path":79,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":80,"sourceHtmlUrl":81},"skill-report.json",16370,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002F5minfutures\u002Farchitecture-reference\u002Fskill-report.json",[83,97,107,116,122,129],{"skillNo":84,"name":85,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":86,"categories":87,"keywords":93,"publishedAt":41},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[88],{"categoryNo":89,"categoryName":90,"taxonomyType":91,"taxonomyTypeDesc":92},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[94,95,96],"model","model hierarchy","model hierarchy skill",{"skillNo":98,"name":99,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":100,"categories":101,"keywords":103,"publishedAt":41},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[102],{"categoryNo":89,"categoryName":90,"taxonomyType":91,"taxonomyTypeDesc":92},[104,105,106],"MCP","zoom","zoom mcp",{"skillNo":108,"name":109,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":110,"categories":111,"keywords":112,"publishedAt":41},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[113,114,115,105],"sdk","zoom apps sdk","apps",{"skillNo":117,"name":118,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":119,"categories":120,"keywords":121,"publishedAt":41},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[118],{"skillNo":123,"name":124,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":125,"categories":126,"keywords":128,"publishedAt":41},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[127],{"categoryNo":89,"categoryName":90,"taxonomyType":91,"taxonomyTypeDesc":92},[124],{"skillNo":130,"name":131,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":132,"categories":133,"keywords":134,"publishedAt":41},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[131]]