architecture-reference
Portfolio Buddyプロジェクトの構成に関する情報を迅速に参照し、新機能の追加や既存コンポーネントの変更、データフローの理解、新規メンバーの参加を円滑に進める上で役立つSkill。
📜 元の英語説明(参考)
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.
🇯🇵 日本人クリエイター向け解説
Portfolio Buddyプロジェクトの構成に関する情報を迅速に参照し、新機能の追加や既存コンポーネントの変更、データフローの理解、新規メンバーの参加を円滑に進める上で役立つSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o architecture-reference.zip https://jpskill.com/download/16748.zip && unzip -o architecture-reference.zip && rm architecture-reference.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/16748.zip -OutFile "$d\architecture-reference.zip"; Expand-Archive "$d\architecture-reference.zip" -DestinationPath $d -Force; ri "$d\architecture-reference.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
architecture-reference.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
architecture-referenceフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
Portfolio Buddy 2 - アーキテクチャリファレンス
コンポーネント階層
App.tsx (351 行)
├── Header
│ └── アプリのタイトルとブランディング
├── UploadSection
│ ├── Supabase へのファイルアップロード
│ ├── CSV の解析と検証
│ └── エラー処理
├── ErrorList
│ └── 解析/検証エラーの表示
├── UploadedFilesList
│ └── 正常にアップロードされたファイルのリスト
├── AnalyticsControls
│ ├── Metrics ビューの切り替え
│ ├── Portfolio ビューの切り替え
│ └── Correlation ビューの切り替え
├── PortfolioSection (591 行 - 要リファクタリング!)
│ ├── usePortfolio hook (日付フィルタリング)
│ ├── useContractMultipliers hook
│ ├── Chart.js によるエクイティカーブ
│ ├── ポートフォリオ統計
│ ├── ContractInput コンポーネント
│ ├── MasterContractControl
│ └── MetricsTable の統合
├── CorrelationSection
│ ├── CorrelationHeatmap (Chart.js)
│ ├── Spearman 相関
│ └── Pearson 相関
├── MetricsTable (242 行)
│ ├── useMetrics hook
│ ├── useSorting hook (高度な複数列ソート)
│ ├── SortableHeader コンポーネント
│ └── 選択状態の管理
└── SessionComplete
└── 完了 UI/メッセージ
主要な Hooks
useMetrics
場所: src/hooks/useMetrics.ts 目的: アップロードされたポートフォリオデータから取引指標を計算する 機能:
- シャープレシオ、ソルティノレシオ、最大ドローダウン、CAGR、勝率などを計算します。
- パフォーマンス向上のためのメモ化された計算
- 空または無効なデータを適切に処理します
使用法:
const { metrics, isCalculating } = useMetrics(portfolioData, riskFreeRate)
戻り値:
metrics: 戦略ごとの計算された指標の配列isCalculating: Boolean 型のローディング状態
注意: ソート比較に 4 つの TypeScript any 違反が含まれています (技術的負債)
usePortfolio
場所: src/hooks/usePortfolio.ts 目的: 日付範囲フィルタリングによるポートフォリオデータの管理 機能:
- CSV 取引データを解析します
- 日付範囲 (開始日/終了日) でフィルタリングします
- エクイティカーブを構築します
- 毎日のリターンを集計します
使用法:
const {
portfolioData,
filteredData,
dateRange,
setDateRange
} = usePortfolio(uploadedFiles)
最近の追加: 日付範囲フィルタリング (commit 258ba3a)
注意: 取引/指標タイプに 11 個の TypeScript any 違反が含まれています (技術的負債)
useContractMultipliers
場所: src/hooks/useContractMultipliers.ts 目的: 先物取引のコントラクト乗数を管理する 機能:
- 戦略ごとのコントラクトサイズ追跡
- 指標に乗数を適用する
- すべてのコントラクトを一度に設定するマスターコントロール
使用法:
const {
multipliers,
setMultiplier,
setAllMultipliers,
getAdjustedMetrics
} = useContractMultipliers(strategies)
useSorting
場所: src/hooks/useSorting.ts 目的: MetricsTable のための高度な複数列ソート 機能:
- 優先度付きの複数列でソート
- 昇順/降順の切り替え
- データ型ごとのカスタム比較ロジック
使用法:
const {
sortedData,
sortColumn,
sortDirection,
handleSort
} = useSorting(data, defaultColumn)
ユーティリティ関数
dataUtils.ts
場所: src/utils/dataUtils.ts コア関数を含む:
CSV & データ処理:
parseCSV(file)- PapaParse で CSV ファイルを解析しますprocessCurrencyColumns(data)- 通貨値 ($, カンマ) をクリーンにしますparseFilenameComponents(filename)- ファイル名からシンボル/方向/戦略を抽出しますgetDisplayName(symbol, direction, strategy)- 表示名をフォーマットしますnormalizeDate(date)- 日付を深夜 UTC に正規化しますgetDateKey(date)- 日付を YYYY-MM-DD 文字列キーに変換します
指標計算:
calculateMetrics(data, filename)- 戦略の取引レベルの指標を計算します- 純利益、総利益/損失
- 利益率、勝率
- 平均勝ち/負け、期待値
- 最大ドローダウン (エクイティカーブから)
- CAGR 相当 (annualGrowthRate)
- 総取引数、勝ち/負け数
- 注意: シャープレシオまたはソルティノレシオは計算しません (これらは PortfolioSection.tsx にあります)
getAdjustedMetrics(metrics, multiplier)- コントラクト乗数を指標に適用します
リスク調整済み指標 (PortfolioSection.tsx):
- シャープレシオ (533 行目):
(annualGrowthRate / 100) / (maxDrawdown / startingCapital)としてインラインで計算されます - ソルティノレシオ (133-158 行目): ダウンサイド偏差でインラインで計算され、リスクフリーレート状態を使用します
相関分析:
buildCorrelationMatrix(strategies)- Spearman 相関行列を構築しますcalculatePearsonCorrelation(returns1, returns2)- Pearson 相関係数calculateRanks(values)- Spearman 相関のランク計算
取引計算:
getMarginRate(symbol)- シンボルごとの証拠金要件を取得しますcalculateEquityCurve(trades)- 累積エクイティカーブを構築しますcalculateDailyReturns(equity)- エクイティカーブから毎日のリターンを計算します
フォーマット:
formatNumber(value, decimals)- 数値を小数点以下でフォーマットしますformatCurrency(value)- 通貨としてフォーマットします ($X,XXX.XX)formatPercent(value)- パーセンテージとしてフォーマットします (X.XX%)
注意: Metrics インターフェースに 1 つの TypeScript any 違反が含まれています (技術的負債)
データフロー
アップロード & 処理フロー
1. ユーザーが UploadSection 経由で CSV をアップロードします
↓
2. parseCSV() が取引データを抽出します
↓
3. processCurrencyColumns() がデータをクリーンにします
↓
4. ファイルが Supabase ストレージにアップロードされます
↓
5. usePortfolio hook がデータをフェッチして集計します
↓
6. 日付範囲フィルターが適用されます (設定されている場合)
↓
7. useMetrics がすべての指標を計算します
↓
8. MetricsTable が結果を表示します
コントラクト乗数フロー
1. ユーザーが ContractInput にコントラクトサイズを入力します
↓
2. useContractMultipliers が値を格納します
↓
3. getAdjustedMetrics() が乗数を適用します
↓
4. 調整された指標が MetricsTable に表示されます
↓
5. 調整された値でポートフォリオチャートが更新されます
ソートフロー
1. ユーザーが SortableHeader をクリックします
↓
2. useSorting がソート列を更新します
(原文はここで切り詰められています) 📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
Portfolio 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