alpha-visualizer 0.3.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.github/workflows/lighthouse.yml +4 -4
- alpha_visualizer-0.3.0/.hypothesis/constants/069853a4f8389a49 → alpha_visualizer-0.4.0/.hypothesis/constants/11405f641e79317e +1 -1
- alpha_visualizer-0.4.0/.hypothesis/constants/14f71fc9be9bf497 +4 -0
- alpha_visualizer-0.4.0/.hypothesis/constants/4720ae237de2a683 +4 -0
- alpha_visualizer-0.4.0/.hypothesis/constants/4726660442f99a00 +4 -0
- alpha_visualizer-0.3.0/.hypothesis/constants/7b2b6a48db4df50a → alpha_visualizer-0.4.0/.hypothesis/constants/6d12ac81de32365c +1 -1
- alpha_visualizer-0.4.0/.hypothesis/constants/ab4df659c6b192db +4 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/CHANGELOG.md +27 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/PKG-INFO +2 -1
- alpha_visualizer-0.4.0/docs/screenshots/en/strategy-signal-tv.png +0 -0
- alpha_visualizer-0.4.0/docs/screenshots/ja/strategy-signal-tv.png +0 -0
- alpha_visualizer-0.4.0/frontend/e2e/fixtures/forge/data/historical/SPY_1d.parquet +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/e2e/fixtures/forge/forge.yaml +2 -0
- alpha_visualizer-0.4.0/frontend/e2e/screenshots/strategy-signal-tv.spec.ts +49 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/openapi.json +191 -1
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/playwright.config.ts +1 -1
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/playwright.screenshots.config.ts +2 -2
- alpha_visualizer-0.4.0/frontend/src/api/__tests__/client.test.ts +101 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/api/client.ts +16 -1
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/api/types.gen.ts +108 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/api/types.ts +10 -0
- alpha_visualizer-0.4.0/frontend/src/charts/tv/StrategySignalChartTV.stories.tsx +243 -0
- alpha_visualizer-0.4.0/frontend/src/charts/tv/StrategySignalChartTV.tsx +174 -0
- alpha_visualizer-0.4.0/frontend/src/charts/tv/__tests__/StrategySignalChartTV.test.tsx +250 -0
- alpha_visualizer-0.4.0/frontend/src/charts/tv/__tests__/trades.test.ts +219 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/tv/data.ts +41 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/tv/theme.ts +75 -0
- alpha_visualizer-0.4.0/frontend/src/charts/tv/trades.ts +181 -0
- alpha_visualizer-0.4.0/frontend/src/hooks/__tests__/useStrategyHistorical.test.tsx +101 -0
- alpha_visualizer-0.4.0/frontend/src/hooks/useStrategyHistorical.ts +35 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/pages/DetailPage.tsx +9 -1
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/screens/StrategyScreen.tsx +10 -2
- alpha_visualizer-0.4.0/frontend/src/screens/strategy/SignalChartCard.tsx +145 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/pyproject.toml +3 -2
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/__init__.py +1 -1
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/app.py +2 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/forge_config.py +9 -0
- alpha_visualizer-0.4.0/src/alpha_visualizer/routers/historical.py +57 -0
- alpha_visualizer-0.4.0/src/alpha_visualizer/schemas/historical.py +41 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/schemas/results.py +9 -1
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/services/backtest.py +36 -2
- alpha_visualizer-0.4.0/src/alpha_visualizer/services/historical.py +145 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/fixtures/build_e2e_fixture.py +48 -1
- alpha_visualizer-0.4.0/tests/routers/test_historical.py +102 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/schemas/test_schemas.py +69 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/services/test_backtest.py +137 -0
- alpha_visualizer-0.4.0/tests/services/test_historical.py +156 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/test_forge_config.py +40 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/uv.lock +46 -1
- alpha_visualizer-0.3.0/.hypothesis/constants/150dfae7c64cc789 +0 -4
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.agents/skills/source-command-audit-licenses/SKILL.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.agents/skills/source-command-pre-release/SKILL.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.claude/commands/audit-licenses.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.claude/commands/pre-release.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.codex/hooks.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.github/ISSUE_TEMPLATE/bug_report_ja.yml +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.github/ISSUE_TEMPLATE/feature_request_ja.yml +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.github/codeql/README.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.github/codeql/codeql-config.yml +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.github/dependabot.yml +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.github/workflows/ci.yml +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.github/workflows/codeql.yml +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.github/workflows/release.yml +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.gitignore +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/.gitignore +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/0bf3463e8f4751b8 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/152293548dfa1dc4 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/291dc4c40995bea6 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/312a7aaf12a1fd47 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/331e194303817b32 +0 -0
- /alpha_visualizer-0.3.0/.hypothesis/constants/0a940b6ee0f389fc → /alpha_visualizer-0.4.0/.hypothesis/constants/368f2bae545df6be +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/3c70931be7dd2e4e +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/3f7b61d4b4a660e1 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/4577b97f57a8a832 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/4a1c4d1532cab28e +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/508b282112ab038e +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/5c12d3619c3f5d5b +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/757b1f8305546439 +0 -0
- /alpha_visualizer-0.3.0/.hypothesis/constants/0b2de83fbd38f835 → /alpha_visualizer-0.4.0/.hypothesis/constants/76d133f3ba15df09 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/7aec89cee7c5a592 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/7d3b67d825fc154a +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/7f90c9d611001617 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/828ed73d45fcee28 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/85f15eb28ea04389 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/89aaa48f251cd53d +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/8add761403393fca +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/96ca93165140d446 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/97982d8e7c8d4a95 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/a5b6e9cccb23f349 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/a636a4647020033d +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/b5803992d2e76cf5 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/b76328deebb21ae6 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/b9ff5bcd3a53e3a7 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/c5349cb90ddc7968 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/c5f6cf064ffb412d +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/c9814af66187059c +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/da39a3ee5e6b4b0d +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/dd2b62c354789905 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/e44a457d795e56c2 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/ea2d606acbfff989 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/ee487c54cd5ca7dc +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/eed5e66c16ae84b8 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/f7c4a04c97c0daf8 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/fa443af6269a6e02 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/.hypothesis/constants/ff4517cbfe51fea1 +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/AGENTS.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/CLAUDE.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/CODE_OF_CONDUCT.en.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/CODE_OF_CONDUCT.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/CONTRIBUTING.en.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/CONTRIBUTING.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/LICENSE +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/README.en.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/README.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/SECURITY.en.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/SECURITY.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/THIRDPARTY_LICENSES.txt +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/cliff.toml +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/docs/adr/0001-pages-vs-screens.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/docs/adr/0002-charts-visx-vs-components.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/docs/adr/0003-openapi-typescript-codegen.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/docs/adr/0004-condition-node-discriminated-union.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/docs/lighthouse-ci.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/docs/screenshots/en/browse.png +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/docs/screenshots/en/compare.png +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/docs/screenshots/en/detail.png +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/docs/screenshots/en/ideas.png +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/docs/screenshots/en/optimize.png +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/docs/screenshots/en/strategy.png +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/docs/screenshots/ja/browse.png +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/docs/screenshots/ja/compare.png +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/docs/screenshots/ja/detail.png +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/docs/screenshots/ja/ideas.png +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/docs/screenshots/ja/optimize.png +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/docs/screenshots/ja/strategy.png +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/.gitignore +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/.npmrc +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/.size-limit.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/.storybook/main.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/.storybook/preview.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/CLAUDE.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/README.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/THIRDPARTY_FONTS.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/e2e/fixtures/README.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/e2e/fixtures/forge/data/ideas/ideas.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/e2e/fixtures/forge/data/results/backtest_results.db +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/e2e/fixtures/forge/data/strategies/momo_breakout.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/e2e/fixtures/forge/data/strategies/rsi_reversal.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/e2e/fixtures/forge/data/strategies/sma_cross.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/e2e/helpers/locators.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/e2e/samples/sample-fixture.spec.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/e2e/screenshots/capture.spec.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/e2e/screenshots/equity-tv.spec.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/e2e/specs/browse.spec.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/e2e/specs/compare.spec.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/e2e/specs/detail.spec.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/e2e/specs/i18n.spec.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/eslint.config.js +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/index.html +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/package.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/playwright.samples.config.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/pnpm-lock.yaml +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/pnpm-workspace.yaml +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/public/favicon.svg +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/public/icons.svg +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/tv/CompareEquityTV.stories.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/tv/CompareEquityTV.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/tv/EquityDrawdownPaneTV.stories.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/tv/EquityDrawdownPaneTV.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/tv/RollingMetricsChartTV.stories.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/tv/RollingMetricsChartTV.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/tv/WFOEquityTV.stories.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/tv/WFOEquityTV.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/tv/__tests__/CompareEquityTV.test.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/tv/__tests__/EquityDrawdownPaneTV.test.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/tv/__tests__/RollingMetricsChartTV.test.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/tv/__tests__/WFOEquityTV.test.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/tv/__tests__/data.test.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/tv/__tests__/theme.test.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/visx/AnnualReturnsBarV.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/visx/CompareEquityV.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/visx/CorrelationHeatmapV.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/visx/DrawdownChartV.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/visx/EquityChartV.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/visx/MAEMFEScatterV.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/visx/MonthlyHeatmapV.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/visx/OptimizeScatterV.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/visx/Sparkline.stories.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/visx/Sparkline.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/visx/__tests__/EquityChartV.regime.test.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/charts/visx/regimeBands.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/CommandPalette.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/DetailToolbar.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/MetricsSummaryBarV2.stories.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/MetricsSummaryBarV2.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/RootLayout.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/SettingsToggles.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/StrategyHero.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/__tests__/CommandPalette.test.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/__tests__/CorrelationHeatmap.test.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/__tests__/responsive-styles.test.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/browser/CompareFloatingBar.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/browser/FilterBar.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/browser/GroupByToggle.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/browser/Heroline.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/browser/RunHistoryTab.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/browser/SavedViews.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/browser/StrategySlidePanel.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/browser/StrategyTable.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/browser/SymbolAtlas.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/browser/SymbolCard.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/charts/AnnualReturnsBar.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/charts/CorrelationHeatmap.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/charts/DrawdownDetailChart.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/charts/MAEMFEScatter.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/charts/MonteCarloChart.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/charts/OptimizeScatter.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/charts/ReturnDistributionChart.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/charts/RollingMetricsChart.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/charts/VaRChart.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/charts/WFOTimeline.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/charts/WeekdayPerformanceChart.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/live/LiveTab.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/live/__tests__/LiveTab.test.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/live/__tests__/format.test.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/live/format.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/metrics/CompareTable.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/metrics/ISOOSMetrics.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/metrics/MetricsGrid.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/metrics/RegimeBreakdownCards.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/metrics/SignalQualityBadge.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/metrics/__tests__/evaluateGood.test.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/metrics/evaluate.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/nav.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/components/trades/TradeTable.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/constants/featureFlags.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/constants/metricDefinitions.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/contexts/DashboardContext.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/contexts/dashboardConstants.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/design/a11y.css +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/design/primitives/Button.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/design/primitives/Card.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/design/primitives/Chip.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/design/primitives/Divider.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/design/primitives/KeyValue.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/design/primitives/OverflowMenu.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/design/primitives/Pill.stories.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/design/primitives/Pill.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/design/primitives/SectionHeader.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/design/primitives/Stat.stories.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/design/primitives/Stat.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/design/primitives/TabBar.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/design/primitives/Toolbar.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/design/primitives/__tests__/OverflowMenu.test.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/design/primitives/index.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/design/tokens.css +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/design/useChartTheme.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/hooks/__tests__/useEquityViewport.test.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/hooks/__tests__/useFetchByKey.test.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/hooks/__tests__/useScrollRestoration.test.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/hooks/__tests__/useStrategyList.test.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/hooks/__tests__/useTheme.test.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/hooks/useBacktestData.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/hooks/useDebounce.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/hooks/useEquityViewport.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/hooks/useFetchByKey.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/hooks/useIdeasList.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/hooks/useRecentStrategies.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/hooks/useScrollRestoration.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/hooks/useSparklineCache.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/hooks/useStrategyList.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/hooks/useSymbolStats.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/hooks/useTheme.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/i18n/__tests__/strings.test.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/i18n/strings.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/__tests__/correlation.test.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/__tests__/distribution.test.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/__tests__/drawdown.test.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/__tests__/format.test.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/__tests__/monteCarlo.properties.test.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/__tests__/monteCarlo.test.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/__tests__/rolling.test.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/__tests__/searchParams.test.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/__tests__/searchStrategies.test.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/__tests__/walkForward.test.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/__tests__/weekday.test.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/assetClass.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/correlation.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/csv.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/distribution.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/drawdown.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/exportPng.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/format.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/monteCarlo.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/rolling.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/searchParams.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/searchStrategies.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/walkForward.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/lib/weekday.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/main.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/mock/btData.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/pages/BrowsePage.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/pages/ComparePage.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/pages/IdeasPage.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/router.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/screens/BacktestScreen.stories.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/screens/BacktestScreen.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/screens/BrowseScreen.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/screens/CompareScreen.stories.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/screens/CompareScreen.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/screens/ISOOSScreen.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/screens/IdeasScreen.stories.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/screens/IdeasScreen.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/screens/OptimizeScreen.stories.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/screens/OptimizeScreen.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/screens/WFOScreen.stories.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/screens/WFOScreen.tsx +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/src/test-setup.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/tsconfig.app.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/tsconfig.e2e.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/tsconfig.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/tsconfig.node.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/frontend/vite.config.ts +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/lighthouserc.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/release.sh +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/README.en.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/README.md +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/__init__.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/_generators/__init__.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/_generators/compatibility_matrix.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/_generators/ideas_defs.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/_generators/pseudo_backtest.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/_generators/pseudo_grid.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/_generators/pseudo_wfo.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/_generators/strategy_defs.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/_generators/synthetic_ohlcv.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/_generators/writers.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/build_samples.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/sample-forge/data/ideas/ideas.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/sample-forge/data/results/backtest_results.db +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/sample-forge/data/strategies/bbands_breakout_v1.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/sample-forge/data/strategies/donchian_turtle_v1.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/sample-forge/data/strategies/ema_adx_macd_v1.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/sample-forge/data/strategies/macd_crossover_v1.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/sample-forge/data/strategies/range_reversion_v1.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/sample-forge/data/strategies/rsi_reversion_v1.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/sample-forge/data/strategies/sma_crossover_v1.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/sample-forge/data/strategies/supertrend_adx_v1.json +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/samples/sample-forge/forge.yaml +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/scripts/generate_openapi.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/cli.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/db.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/dependencies.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/errors.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/log_sanitize.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/repositories/__init__.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/repositories/backtest_results.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/repositories/ideas.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/repositories/live.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/repositories/optimization.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/repositories/strategies.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/routers/__init__.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/routers/ideas.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/routers/live.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/routers/optimize.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/routers/results.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/routers/run.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/routers/strategies.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/routers/wfo.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/schemas/__init__.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/schemas/ideas.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/schemas/live.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/schemas/optimize.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/schemas/strategies.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/schemas/wfo.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/services/__init__.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/services/live.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/src/alpha_visualizer/services/walk_forward.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/__init__.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/conftest.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/factories.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/repositories/__init__.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/repositories/test_backtest_results_repo.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/repositories/test_ideas_reader.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/repositories/test_live_repo.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/repositories/test_optimization_repo.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/repositories/test_strategies_repo.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/routers/__init__.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/routers/test_forge_yaml_integration.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/routers/test_ideas.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/routers/test_live.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/routers/test_optimize.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/routers/test_results.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/routers/test_run.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/routers/test_strategies.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/routers/test_wfo.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/samples/__init__.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/samples/test_pseudo_backtest.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/samples/test_pseudo_grid.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/samples/test_pseudo_wfo.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/samples/test_sample_forge.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/samples/test_strategy_defs.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/samples/test_synthetic_ohlcv.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/samples/test_writers.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/schemas/__init__.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/services/__init__.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/services/test_backtest_properties.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/services/test_live.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/services/test_wfo.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/test_app.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/test_cli.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/test_db.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/test_dependencies.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/test_errors.py +0 -0
- {alpha_visualizer-0.3.0 → alpha_visualizer-0.4.0}/tests/test_log_sanitize.py +0 -0
|
@@ -54,20 +54,20 @@ jobs:
|
|
|
54
54
|
working-directory: frontend
|
|
55
55
|
run: pnpm run build
|
|
56
56
|
|
|
57
|
-
- name: Start vis serve
|
|
57
|
+
- name: Start alpha-vis serve
|
|
58
58
|
run: |
|
|
59
|
-
uv run vis serve \
|
|
59
|
+
uv run alpha-vis serve \
|
|
60
60
|
--forge-dir frontend/e2e/fixtures/forge \
|
|
61
61
|
--port 8123 &
|
|
62
62
|
# 起動待機(最大 30 秒)
|
|
63
63
|
for i in $(seq 1 30); do
|
|
64
64
|
if curl -fsS http://127.0.0.1:8123/health > /dev/null 2>&1; then
|
|
65
|
-
echo "vis serve is up"
|
|
65
|
+
echo "alpha-vis serve is up"
|
|
66
66
|
exit 0
|
|
67
67
|
fi
|
|
68
68
|
sleep 1
|
|
69
69
|
done
|
|
70
|
-
echo "::error::vis serve did not start within 30s"
|
|
70
|
+
echo "::error::alpha-vis serve did not start within 30s"
|
|
71
71
|
exit 1
|
|
72
72
|
|
|
73
73
|
- name: Run Lighthouse CI
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
# file: /home/runner/work/alpha-visualizer/alpha-visualizer/src/alpha_visualizer/forge_config.py
|
|
2
2
|
# hypothesis_version: 6.152.4
|
|
3
3
|
|
|
4
|
-
['FORGE_CONFIG', 'backtest_results.db', 'data', 'db_filename', 'forge.yaml', 'ideas', 'ideas.json', 'ideas_path', 'live', 'output_path', 'path', 'report', 'results', 'strategies', 'strategies.db', 'use_db', 'utf-8']
|
|
4
|
+
['FORGE_CONFIG', 'backtest_results.db', 'data', 'db_filename', 'forge.yaml', 'historical', 'ideas', 'ideas.json', 'ideas_path', 'live', 'output_path', 'path', 'report', 'results', 'storage_path', 'strategies', 'strategies.db', 'use_db', 'utf-8']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/alpha-visualizer/alpha-visualizer/src/alpha_visualizer/services/backtest.py
|
|
2
|
+
# hypothesis_version: 6.152.4
|
|
3
|
+
|
|
4
|
+
[0.0, 1.0, 100.0, '+00:00', '-', '1d', 'Z', 'aggregates', 'annual_returns', 'avg_holding_days', 'build_detail', 'buy_hold_curve', 'buy_hold_equity', 'cagr_pct', 'calmar_ratio', 'compute_drawdown', 'daily_returns', 'date', 'dates', 'direction', 'drawdown', 'end', 'entry_date', 'entry_price', 'equity', 'equity_curve', 'exit_date', 'exit_price', 'filter_by_since', 'holding_days', 'id', 'index', 'is_cutoff', 'is_metrics', 'label_names', 'long', 'mae_pct', 'max_drawdown_pct', 'metrics', 'mfe_pct', 'monthly_returns', 'n_states', 'oos_metrics', 'oos_start', 'parse_dt', 'per_trade_mae_pct', 'per_trade_mfe_pct', 'period', 'periods', 'pnl', 'profit_factor', 'regime_breakdown', 'regime_series', 'return_pct', 'row_to_dict', 'run_at', 'run_id', 'shape_annual_returns', 'shape_equity', 'shape_regime_series', 'shape_trades', 'sharpe_ratio', 'short', 'signal', 'sl_price', 'sortino_ratio', 'split_metrics', 'start', 'states', 'strategy_id', 'strategy_name', 'summarize_row', 'symbol', 'timeframe', 'total_return_pct', 'total_trades', 'tp_price', 'trade_analysis', 'trades', 'value', 'values', 'win_rate_pct']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/alpha-visualizer/alpha-visualizer/src/alpha_visualizer/services/historical.py
|
|
2
|
+
# hypothesis_version: 6.152.4
|
|
3
|
+
|
|
4
|
+
['\x00', '%Y-%m-%d', '%Y-%m-%dT%H:%M:%S', '..', '/', 'Close', 'High', 'Low', 'Open', 'Volume', '\\', 'close', 'coerce', 'high', 'low', 'open', 'symbol が空です', 'time', 'volume']
|
|
@@ -3,6 +3,33 @@
|
|
|
3
3
|
alpha-visualizer の全バージョン変更履歴です。
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
## [0.4.0] - 2026-05-17
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- **TradingView lightweight-charts による「シグナル時系列」セクションを `StrategyScreen` に新規追加** (#191, #186, #197)
|
|
11
|
+
- OHLC ローソク + entry / exit markers (long/short × win/loss で 4 色分け) + SL / TP / entry の priceLine(focus trade は open trade 優先、無ければ最新 closed)
|
|
12
|
+
- regime 切替点に circle marker(`?tv=1` ON 時、`BacktestDetail.regime_series` 経由)
|
|
13
|
+
- `chart.takeScreenshot()` による PNG export ハンドル
|
|
14
|
+
- feature flag `?tv=1` OFF 時は実験機能 placeholder
|
|
15
|
+
- Storybook 6 stories(AtelierClosedTrades / LabOpenTrade / SLHit / TPHit / DenseMarkers / WithRegime)
|
|
16
|
+
- **OHLC 時系列 API** `GET /api/historical/{symbol}?interval=1d&start=&end=` を追加 (#189)
|
|
17
|
+
- `{symbol}_{interval}.parquet` を読んで lightweight-charts 互換の bars 配列を返す
|
|
18
|
+
- `ForgeConfig.historical_dir` を `forge.yaml` の `data.storage_path` から解決(既定 `<forge_dir>/data/historical`)
|
|
19
|
+
- 依存 `pyarrow>=15.0` を追加
|
|
20
|
+
- **`schemas/results.Trade` に `exit_price` / `sl_price` / `tp_price` を追加** (#189)
|
|
21
|
+
- alpha-forge の `_calc_trade_list` 拡張(ysakae/alpha-forge#751)の出力を透過 pickup
|
|
22
|
+
- **frontend `api.getHistorical(symbol, interval, range?)` と `useStrategyHistorical(symbol)` フック追加** (#190)
|
|
23
|
+
- `useFetchByKey` ベースの薄いラッパー、interval 切替時の再 fetch にも対応
|
|
24
|
+
|
|
25
|
+
### Fixes
|
|
26
|
+
|
|
27
|
+
- **trades のソースを `metrics_json.trades` 優先に切替** (#198)
|
|
28
|
+
- alpha-forge は trades を 2 経路で保存(`metrics_json.trades` は snake_case、`trades_json` 列は vectorbt records_readable の PascalCase)
|
|
29
|
+
- 旧実装は PascalCase 列のみ参照しており `shape_trades` が値を読めず、実 backtest 結果で entry/exit markers / exit_price / sl_price / tp_price が常に機能しなかった
|
|
30
|
+
- snake_case → PascalCase の優先順位で解決し、新規・既存両方の backtest 結果で markers / priceLine が描画されるよう修正
|
|
31
|
+
|
|
32
|
+
|
|
6
33
|
## [0.3.0] - 2026-05-16
|
|
7
34
|
|
|
8
35
|
### ⚠️ Breaking Changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: alpha-visualizer
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Web visualization tool for AlphaForge backtest results
|
|
5
5
|
Project-URL: Homepage, https://github.com/alforge-labs/alpha-visualizer
|
|
6
6
|
Project-URL: Repository, https://github.com/alforge-labs/alpha-visualizer
|
|
@@ -23,6 +23,7 @@ Requires-Python: >=3.12
|
|
|
23
23
|
Requires-Dist: click>=8.1
|
|
24
24
|
Requires-Dist: fastapi>=0.115
|
|
25
25
|
Requires-Dist: pandas>=2.0
|
|
26
|
+
Requires-Dist: pyarrow>=15.0
|
|
26
27
|
Requires-Dist: pyyaml>=6.0
|
|
27
28
|
Requires-Dist: rich>=13.0
|
|
28
29
|
Requires-Dist: sqlalchemy>=2.0
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { test } from '@playwright/test'
|
|
2
|
+
import { mkdir } from 'node:fs/promises'
|
|
3
|
+
import { dirname, resolve } from 'node:path'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
import { clearViewerSettings } from '../helpers/locators'
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
8
|
+
const __dirname = dirname(__filename)
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* issue #191 — StrategyScreen の `<SignalChartCard>` (TV candlestick + markers + priceLine)
|
|
12
|
+
* を `?tv=1` で有効化して撮影。
|
|
13
|
+
*
|
|
14
|
+
* 出力先: <repo-root>/docs/screenshots/{ja,en}/strategy-signal-tv.png
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const STRATEGY_ID = 'sma_cross'
|
|
18
|
+
const SCREENSHOT_DIR = resolve(__dirname, '../../../docs/screenshots')
|
|
19
|
+
|
|
20
|
+
async function ensureDir(filePath: string): Promise<void> {
|
|
21
|
+
await mkdir(dirname(filePath), { recursive: true })
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
test.describe.serial('StrategySignalChartTV スクリーンショット', () => {
|
|
25
|
+
for (const lang of ['ja', 'en'] as const) {
|
|
26
|
+
test(`strategy-signal-tv (${lang})`, async ({ page }) => {
|
|
27
|
+
await clearViewerSettings(page)
|
|
28
|
+
const suffix = `?tv=1${lang === 'en' ? '&lang=en' : ''}`
|
|
29
|
+
await page.goto(`/detail/${STRATEGY_ID}${suffix}`)
|
|
30
|
+
await page.waitForLoadState('networkidle')
|
|
31
|
+
|
|
32
|
+
// Strategy タブをクリックして SignalChartCard を表示させる
|
|
33
|
+
const tabName = lang === 'ja' ? '戦略構成' : 'Strategy'
|
|
34
|
+
const tab = page.getByRole('tab', { name: tabName }).first()
|
|
35
|
+
if (await tab.count()) {
|
|
36
|
+
await tab.click()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// SignalChartCard の chart コンテナを待つ
|
|
40
|
+
await page.locator('[data-testid="strategy-signal-chart-tv"]').waitFor()
|
|
41
|
+
// チャート描画完了の余裕(lightweight-charts の Canvas 初期化)
|
|
42
|
+
await page.waitForTimeout(300)
|
|
43
|
+
|
|
44
|
+
const out = resolve(SCREENSHOT_DIR, lang, 'strategy-signal-tv.png')
|
|
45
|
+
await ensureDir(out)
|
|
46
|
+
await page.screenshot({ path: out })
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
})
|
|
@@ -502,6 +502,89 @@
|
|
|
502
502
|
}
|
|
503
503
|
}
|
|
504
504
|
},
|
|
505
|
+
"/api/historical/{symbol}": {
|
|
506
|
+
"get": {
|
|
507
|
+
"summary": "Get Historical",
|
|
508
|
+
"description": "指定 symbol × interval の OHLC ローソク足を返す。\n\n404: historical_dir 不在 or parquet ファイル不在\n400: symbol が不正、または start/end の形式不正",
|
|
509
|
+
"operationId": "get_historical_api_historical__symbol__get",
|
|
510
|
+
"parameters": [
|
|
511
|
+
{
|
|
512
|
+
"name": "symbol",
|
|
513
|
+
"in": "path",
|
|
514
|
+
"required": true,
|
|
515
|
+
"schema": {
|
|
516
|
+
"type": "string",
|
|
517
|
+
"title": "Symbol"
|
|
518
|
+
}
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
"name": "interval",
|
|
522
|
+
"in": "query",
|
|
523
|
+
"required": false,
|
|
524
|
+
"schema": {
|
|
525
|
+
"type": "string",
|
|
526
|
+
"pattern": "^(1m|2m|5m|15m|30m|60m|90m|1h|4h|1d|5d|1wk|1mo|3mo)$",
|
|
527
|
+
"default": "1d",
|
|
528
|
+
"title": "Interval"
|
|
529
|
+
}
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
"name": "start",
|
|
533
|
+
"in": "query",
|
|
534
|
+
"required": false,
|
|
535
|
+
"schema": {
|
|
536
|
+
"anyOf": [
|
|
537
|
+
{
|
|
538
|
+
"type": "string"
|
|
539
|
+
},
|
|
540
|
+
{
|
|
541
|
+
"type": "null"
|
|
542
|
+
}
|
|
543
|
+
],
|
|
544
|
+
"title": "Start"
|
|
545
|
+
}
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
"name": "end",
|
|
549
|
+
"in": "query",
|
|
550
|
+
"required": false,
|
|
551
|
+
"schema": {
|
|
552
|
+
"anyOf": [
|
|
553
|
+
{
|
|
554
|
+
"type": "string"
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
"type": "null"
|
|
558
|
+
}
|
|
559
|
+
],
|
|
560
|
+
"title": "End"
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
],
|
|
564
|
+
"responses": {
|
|
565
|
+
"200": {
|
|
566
|
+
"description": "Successful Response",
|
|
567
|
+
"content": {
|
|
568
|
+
"application/json": {
|
|
569
|
+
"schema": {
|
|
570
|
+
"$ref": "#/components/schemas/HistoricalResponse"
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
},
|
|
575
|
+
"422": {
|
|
576
|
+
"description": "Validation Error",
|
|
577
|
+
"content": {
|
|
578
|
+
"application/json": {
|
|
579
|
+
"schema": {
|
|
580
|
+
"$ref": "#/components/schemas/HTTPValidationError"
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
},
|
|
505
588
|
"/health": {
|
|
506
589
|
"get": {
|
|
507
590
|
"summary": "Health",
|
|
@@ -844,6 +927,34 @@
|
|
|
844
927
|
"type": "object",
|
|
845
928
|
"title": "HTTPValidationError"
|
|
846
929
|
},
|
|
930
|
+
"HistoricalResponse": {
|
|
931
|
+
"properties": {
|
|
932
|
+
"symbol": {
|
|
933
|
+
"type": "string",
|
|
934
|
+
"title": "Symbol"
|
|
935
|
+
},
|
|
936
|
+
"interval": {
|
|
937
|
+
"type": "string",
|
|
938
|
+
"title": "Interval"
|
|
939
|
+
},
|
|
940
|
+
"bars": {
|
|
941
|
+
"items": {
|
|
942
|
+
"$ref": "#/components/schemas/OhlcBar"
|
|
943
|
+
},
|
|
944
|
+
"type": "array",
|
|
945
|
+
"title": "Bars"
|
|
946
|
+
}
|
|
947
|
+
},
|
|
948
|
+
"additionalProperties": true,
|
|
949
|
+
"type": "object",
|
|
950
|
+
"required": [
|
|
951
|
+
"symbol",
|
|
952
|
+
"interval",
|
|
953
|
+
"bars"
|
|
954
|
+
],
|
|
955
|
+
"title": "HistoricalResponse",
|
|
956
|
+
"description": "OHLC 時系列のレスポンスエンベロープ。\n\n`bars` 配列に加えて symbol / interval を返すことで、フロント側で\n複数 symbol のキャッシュを取り違えないよう識別子を付与する。"
|
|
957
|
+
},
|
|
847
958
|
"Idea": {
|
|
848
959
|
"properties": {
|
|
849
960
|
"idea_id": {
|
|
@@ -1300,6 +1411,52 @@
|
|
|
1300
1411
|
"title": "LiveTrade",
|
|
1301
1412
|
"description": "live trades JSON を正規化した 1 件。"
|
|
1302
1413
|
},
|
|
1414
|
+
"OhlcBar": {
|
|
1415
|
+
"properties": {
|
|
1416
|
+
"time": {
|
|
1417
|
+
"type": "string",
|
|
1418
|
+
"title": "Time"
|
|
1419
|
+
},
|
|
1420
|
+
"open": {
|
|
1421
|
+
"type": "number",
|
|
1422
|
+
"title": "Open"
|
|
1423
|
+
},
|
|
1424
|
+
"high": {
|
|
1425
|
+
"type": "number",
|
|
1426
|
+
"title": "High"
|
|
1427
|
+
},
|
|
1428
|
+
"low": {
|
|
1429
|
+
"type": "number",
|
|
1430
|
+
"title": "Low"
|
|
1431
|
+
},
|
|
1432
|
+
"close": {
|
|
1433
|
+
"type": "number",
|
|
1434
|
+
"title": "Close"
|
|
1435
|
+
},
|
|
1436
|
+
"volume": {
|
|
1437
|
+
"anyOf": [
|
|
1438
|
+
{
|
|
1439
|
+
"type": "number"
|
|
1440
|
+
},
|
|
1441
|
+
{
|
|
1442
|
+
"type": "null"
|
|
1443
|
+
}
|
|
1444
|
+
],
|
|
1445
|
+
"title": "Volume"
|
|
1446
|
+
}
|
|
1447
|
+
},
|
|
1448
|
+
"additionalProperties": true,
|
|
1449
|
+
"type": "object",
|
|
1450
|
+
"required": [
|
|
1451
|
+
"time",
|
|
1452
|
+
"open",
|
|
1453
|
+
"high",
|
|
1454
|
+
"low",
|
|
1455
|
+
"close"
|
|
1456
|
+
],
|
|
1457
|
+
"title": "OhlcBar",
|
|
1458
|
+
"description": "1 本のローソク足 (open / high / low / close + volume)。\n\n`time` は ISO 8601 文字列(日足は ``YYYY-MM-DD``、intraday は\n``YYYY-MM-DDTHH:MM:SS``)。`volume` は無いカラムの parquet では None。"
|
|
1459
|
+
},
|
|
1303
1460
|
"OptimizationHistoryEntry": {
|
|
1304
1461
|
"properties": {
|
|
1305
1462
|
"trial": {
|
|
@@ -1924,6 +2081,39 @@
|
|
|
1924
2081
|
"title": "Entry Price",
|
|
1925
2082
|
"default": 0.0
|
|
1926
2083
|
},
|
|
2084
|
+
"exit_price": {
|
|
2085
|
+
"anyOf": [
|
|
2086
|
+
{
|
|
2087
|
+
"type": "number"
|
|
2088
|
+
},
|
|
2089
|
+
{
|
|
2090
|
+
"type": "null"
|
|
2091
|
+
}
|
|
2092
|
+
],
|
|
2093
|
+
"title": "Exit Price"
|
|
2094
|
+
},
|
|
2095
|
+
"sl_price": {
|
|
2096
|
+
"anyOf": [
|
|
2097
|
+
{
|
|
2098
|
+
"type": "number"
|
|
2099
|
+
},
|
|
2100
|
+
{
|
|
2101
|
+
"type": "null"
|
|
2102
|
+
}
|
|
2103
|
+
],
|
|
2104
|
+
"title": "Sl Price"
|
|
2105
|
+
},
|
|
2106
|
+
"tp_price": {
|
|
2107
|
+
"anyOf": [
|
|
2108
|
+
{
|
|
2109
|
+
"type": "number"
|
|
2110
|
+
},
|
|
2111
|
+
{
|
|
2112
|
+
"type": "null"
|
|
2113
|
+
}
|
|
2114
|
+
],
|
|
2115
|
+
"title": "Tp Price"
|
|
2116
|
+
},
|
|
1927
2117
|
"return_pct": {
|
|
1928
2118
|
"type": "number",
|
|
1929
2119
|
"title": "Return Pct",
|
|
@@ -1957,7 +2147,7 @@
|
|
|
1957
2147
|
"direction"
|
|
1958
2148
|
],
|
|
1959
2149
|
"title": "Trade",
|
|
1960
|
-
"description": "``BacktestDetail.trades`` の 1
|
|
2150
|
+
"description": "``BacktestDetail.trades`` の 1 件。\n\n``exit_price`` / ``sl_price`` / ``tp_price`` は TradingView lightweight-charts\nの markers / priceLine 表示用に追加されたフィールド (#189)。\nalpha-forge 側が値を出力していない場合 ``None`` のままになる。"
|
|
1961
2151
|
},
|
|
1962
2152
|
"ValidationError": {
|
|
1963
2153
|
"properties": {
|
|
@@ -32,7 +32,7 @@ export default defineConfig({
|
|
|
32
32
|
// FORGE_CONFIG が外部 forge.yaml を指しているとフィクスチャが上書きされるので明示クリア。
|
|
33
33
|
// --forge-config も併せて明示することで二重に保護する。
|
|
34
34
|
command:
|
|
35
|
-
'env FORGE_CONFIG= uv run vis serve --forge-dir frontend/e2e/fixtures/forge --forge-config frontend/e2e/fixtures/forge/forge.yaml --host 127.0.0.1 --port 8123 --no-open',
|
|
35
|
+
'env FORGE_CONFIG= uv run alpha-vis serve --forge-dir frontend/e2e/fixtures/forge --forge-config frontend/e2e/fixtures/forge/forge.yaml --host 127.0.0.1 --port 8123 --no-open',
|
|
36
36
|
url: `${BASE_URL}/health`,
|
|
37
37
|
cwd: '..',
|
|
38
38
|
reuseExistingServer: !process.env.CI,
|
|
@@ -5,7 +5,7 @@ const BASE_URL = `http://127.0.0.1:${PORT}`
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* README / alforge-labs サイト掲載用スクリーンショット撮影専用 config。
|
|
8
|
-
* 既存の e2e フィクスチャを流用して `vis serve` を自動起動し、
|
|
8
|
+
* 既存の e2e フィクスチャを流用して `alpha-vis serve` を自動起動し、
|
|
9
9
|
* `e2e/screenshots/capture.spec.ts` から各画面を順次撮影する。
|
|
10
10
|
*
|
|
11
11
|
* 出力先: ../docs/screenshots/{ja,en}/<page>.png
|
|
@@ -32,7 +32,7 @@ export default defineConfig({
|
|
|
32
32
|
],
|
|
33
33
|
webServer: {
|
|
34
34
|
command:
|
|
35
|
-
'env FORGE_CONFIG= uv run vis serve --forge-dir frontend/e2e/fixtures/forge --forge-config frontend/e2e/fixtures/forge/forge.yaml --host 127.0.0.1 --port 8124 --no-open',
|
|
35
|
+
'env FORGE_CONFIG= uv run alpha-vis serve --forge-dir frontend/e2e/fixtures/forge --forge-config frontend/e2e/fixtures/forge/forge.yaml --host 127.0.0.1 --port 8124 --no-open',
|
|
36
36
|
url: `${BASE_URL}/health`,
|
|
37
37
|
cwd: '..',
|
|
38
38
|
reuseExistingServer: !process.env.CI,
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
import { ApiError, api } from '../client'
|
|
3
|
+
import type { HistoricalResponse } from '../types'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `api.getHistorical` の URL 構築と response handling を検証する。
|
|
7
|
+
* fetch を vi.spyOn で乗っ取り、呼び出し URL と返却値を直接アサートする。
|
|
8
|
+
*/
|
|
9
|
+
describe('api.getHistorical', () => {
|
|
10
|
+
const sampleResponse: HistoricalResponse = {
|
|
11
|
+
symbol: 'SPY',
|
|
12
|
+
interval: '1d',
|
|
13
|
+
bars: [
|
|
14
|
+
{ time: '2025-01-02', open: 400, high: 405, low: 399, close: 403.5, volume: 1_000_000 },
|
|
15
|
+
],
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let fetchSpy: ReturnType<typeof vi.spyOn>
|
|
19
|
+
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
fetchSpy = vi.spyOn(globalThis, 'fetch')
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
afterEach(() => {
|
|
25
|
+
fetchSpy.mockRestore()
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
function mockJsonResponse(body: unknown, status = 200): void {
|
|
29
|
+
fetchSpy.mockResolvedValueOnce(
|
|
30
|
+
new Response(JSON.stringify(body), {
|
|
31
|
+
status,
|
|
32
|
+
headers: { 'Content-Type': 'application/json' },
|
|
33
|
+
}),
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
it('既定 interval=1d で /api/historical/{symbol}?interval=1d を呼ぶ', async () => {
|
|
38
|
+
mockJsonResponse(sampleResponse)
|
|
39
|
+
|
|
40
|
+
const result = await api.getHistorical('SPY')
|
|
41
|
+
|
|
42
|
+
expect(fetchSpy).toHaveBeenCalledTimes(1)
|
|
43
|
+
const url = String(fetchSpy.mock.calls[0]?.[0])
|
|
44
|
+
expect(url).toBe('/api/historical/SPY?interval=1d')
|
|
45
|
+
expect(result).toEqual(sampleResponse)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('interval を指定するとクエリに反映される', async () => {
|
|
49
|
+
mockJsonResponse(sampleResponse)
|
|
50
|
+
|
|
51
|
+
await api.getHistorical('AAPL', '1h')
|
|
52
|
+
|
|
53
|
+
const url = String(fetchSpy.mock.calls[0]?.[0])
|
|
54
|
+
expect(url).toBe('/api/historical/AAPL?interval=1h')
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('range の start/end がクエリに乗る', async () => {
|
|
58
|
+
mockJsonResponse(sampleResponse)
|
|
59
|
+
|
|
60
|
+
await api.getHistorical('SPY', '1d', { start: '2024-01-02', end: '2024-03-25' })
|
|
61
|
+
|
|
62
|
+
const url = String(fetchSpy.mock.calls[0]?.[0])
|
|
63
|
+
expect(url).toBe(
|
|
64
|
+
'/api/historical/SPY?interval=1d&start=2024-01-02&end=2024-03-25',
|
|
65
|
+
)
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('range の start のみでも end が無ければ start のみ乗る', async () => {
|
|
69
|
+
mockJsonResponse(sampleResponse)
|
|
70
|
+
|
|
71
|
+
await api.getHistorical('SPY', '1d', { start: '2024-01-02' })
|
|
72
|
+
|
|
73
|
+
const url = String(fetchSpy.mock.calls[0]?.[0])
|
|
74
|
+
expect(url).toBe('/api/historical/SPY?interval=1d&start=2024-01-02')
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
it('symbol に special 文字が含まれていれば encode される', async () => {
|
|
78
|
+
mockJsonResponse(sampleResponse)
|
|
79
|
+
|
|
80
|
+
await api.getHistorical('CL=F')
|
|
81
|
+
|
|
82
|
+
const url = String(fetchSpy.mock.calls[0]?.[0])
|
|
83
|
+
expect(url).toBe('/api/historical/CL%3DF?interval=1d')
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it('404 のとき ApiError を throw する', async () => {
|
|
87
|
+
mockJsonResponse({ detail: 'not found' }, 404)
|
|
88
|
+
|
|
89
|
+
const err = await api.getHistorical('UNKNOWN').then(
|
|
90
|
+
() => {
|
|
91
|
+
throw new Error('expected getHistorical to reject')
|
|
92
|
+
},
|
|
93
|
+
(e: unknown) => e,
|
|
94
|
+
)
|
|
95
|
+
expect(err).toBeInstanceOf(ApiError)
|
|
96
|
+
expect(err).toMatchObject({
|
|
97
|
+
status: 404,
|
|
98
|
+
url: '/api/historical/UNKNOWN?interval=1d',
|
|
99
|
+
})
|
|
100
|
+
})
|
|
101
|
+
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BacktestDetail, IdeaItem, LiveDetailResponse, LiveListItem, OptimizeResult, StrategyComparison, StrategyDetail, StrategyListItem, StrategyRun, WFOResult } from './types'
|
|
1
|
+
import type { BacktestDetail, HistoricalResponse, IdeaItem, LiveDetailResponse, LiveListItem, OptimizeResult, StrategyComparison, StrategyDetail, StrategyListItem, StrategyRun, WFOResult } from './types'
|
|
2
2
|
|
|
3
3
|
const API_BASE = '/api'
|
|
4
4
|
|
|
@@ -98,6 +98,21 @@ export const api = {
|
|
|
98
98
|
const qs = runId ? `?run_id=${encodeURIComponent(runId)}` : ''
|
|
99
99
|
return request<LiveDetailResponse>(`/live/${encodeURIComponent(strategyId)}${qs}`)
|
|
100
100
|
},
|
|
101
|
+
|
|
102
|
+
// OHLC 時系列(#189 で backend に追加)。
|
|
103
|
+
// backend の /api/historical/{symbol} を呼び lightweight-charts 互換の bars を取得する。
|
|
104
|
+
getHistorical: (
|
|
105
|
+
symbol: string,
|
|
106
|
+
interval: string = '1d',
|
|
107
|
+
range?: { start?: string; end?: string },
|
|
108
|
+
): Promise<HistoricalResponse> => {
|
|
109
|
+
const params = new URLSearchParams({ interval })
|
|
110
|
+
if (range?.start) params.set('start', range.start)
|
|
111
|
+
if (range?.end) params.set('end', range.end)
|
|
112
|
+
return request<HistoricalResponse>(
|
|
113
|
+
`/historical/${encodeURIComponent(symbol)}?${params.toString()}`,
|
|
114
|
+
)
|
|
115
|
+
},
|
|
101
116
|
}
|
|
102
117
|
|
|
103
118
|
export { ApiError }
|