Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
"name": "quant-stock-technical",
"displayName": "Quant Stock Technical",
"source": "./plugins/quant-stock-technical",
"description": "Acquire audited KIS Korean and U.S. EOD data and screen a deterministic KOSPI, KOSDAQ, NYSE, and NASDAQ technical universe.",
"version": "0.4.5",
"description": "Acquire audited KIS EOD data, screen four exchanges, and evaluate selected opening-hour outcomes.",
"version": "0.4.6",
"author": {
"name": "mrcha033"
},
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ jobs:
run: python -B skills/quant-stock-technical/scripts/collect_open1h_research.py --self-test
- name: Run opening-hour evaluator self-test
run: python -B skills/quant-stock-technical/scripts/evaluate_open1h_research.py --self-test
- name: Run selected opening-hour outcomes self-test
run: python -B skills/quant-stock-technical/scripts/selected_open1h_outcomes.py --self-test
- name: Run selected opening-hour walk-forward self-test
run: python -B skills/quant-stock-technical/scripts/walk_forward_open1h.py --self-test
- name: Run four-exchange universe builder self-test
run: python -B skills/quant-stock-technical/scripts/build_universe_manifest.py --self-test
- name: Run deterministic universe screen self-test
Expand Down
4 changes: 2 additions & 2 deletions plugins/quant-stock-technical/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "quant-stock-technical",
"displayName": "Quant Stock Technical",
"version": "0.4.5",
"description": "Acquire audited KIS Korean and U.S. EOD data and screen a deterministic KOSPI, KOSDAQ, NYSE, and NASDAQ technical universe.",
"version": "0.4.6",
"description": "Acquire audited KIS EOD data, screen four exchanges, and evaluate selected opening-hour outcomes.",
"author": {
"name": "mrcha033",
"url": "https://github.com/mrcha033"
Expand Down
10 changes: 5 additions & 5 deletions plugins/quant-stock-technical/.codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "quant-stock-technical",
"version": "0.4.5",
"description": "Acquire audited KIS Korean and U.S. EOD data and screen a deterministic four-exchange stock universe.",
"version": "0.4.6",
"description": "Acquire audited KIS EOD data, screen four exchanges, and evaluate selected opening-hour outcomes.",
"author": {
"name": "mrcha033",
"url": "https://github.com/mrcha033"
Expand All @@ -16,8 +16,8 @@
"skills": "./skills/",
"interface": {
"displayName": "Quant Stock Technical",
"shortDescription": "Four-exchange EOD acquisition and screening",
"longDescription": "Acquire resumable read-only KIS Korean and U.S. adjusted EOD data, audit invalid provider rows without interpolation, and build a source-hashed KOSPI, KOSDAQ, NYSE, and NASDAQ universe.",
"shortDescription": "Four-exchange screening and opening-hour research",
"longDescription": "Acquire resumable read-only KIS Korean and U.S. adjusted EOD data, build a source-hashed four-exchange universe, and evaluate frozen selected candidates against opening-hour outcomes.",
"developerName": "mrcha033",
"category": "Finance",
"capabilities": [
Expand All @@ -28,7 +28,7 @@
"defaultPrompt": [
"Acquire resumable read-only KIS Korean and U.S. adjusted-EOD bundles.",
"Calculate a technical report from these completed OHLCV files.",
"Build and screen a frozen four-exchange technical universe."
"Evaluate frozen selected candidates against opening-hour outcomes."
]
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: quant-stock-technical
description: Acquire resumable read-only KIS Korean and U.S. adjusted-EOD bundles, calculate reproducible numbers-only stock technical analysis, and screen deterministic KOSPI, KOSDAQ, NYSE, and NASDAQ target universes. Use when the user needs completed historical OHLCV and benchmarks, an as-of-date market/ticker report, short-, medium-, and long-horizon opinions, a quantitative risk counterpoint, entry/stop/take-profit levels, a 0-100 technical-strength score, or a frozen exchange-aware screen for a separate execution system. Do not use news, fundamentals, analyst views, narrative judgment, intraday execution, or live-order claims.
description: Acquire resumable read-only KIS Korean and U.S. adjusted-EOD bundles, calculate reproducible numbers-only stock technical analysis, screen deterministic KOSPI, KOSDAQ, NYSE, and NASDAQ target universes, and evaluate frozen selected candidates against opening-hour outcomes. Use when the user needs completed historical OHLCV and benchmarks, an as-of-date market/ticker report, short-, medium-, and long-horizon opinions, a quantitative risk counterpoint, entry/stop/take-profit levels, a 0-100 technical-strength score, a frozen exchange-aware screen, or a read-only point-in-time or explicitly survivor-biased walk-forward diagnostic. Do not use news, fundamentals, analyst views, narrative judgment, intraday execution, or live-order claims.
---

# Quant Stock Technical
Expand Down Expand Up @@ -104,9 +104,17 @@ python3 scripts/build_universe_manifest.py --self-test
python3 scripts/analyze_stock_v2.py --self-test
python3 scripts/collect_open1h_research.py --self-test
python3 scripts/evaluate_open1h_research.py --self-test
python3 scripts/selected_open1h_outcomes.py --self-test
python3 scripts/walk_forward_open1h.py --self-test
python3 scripts/screen_universe.py --self-test
```

For a longer selected-candidate diagnostic, use
`scripts/walk_forward_open1h.py`. It holds one source manifest membership
static across prior sessions and therefore labels the result
`STATIC_SOURCE_MANIFEST_SURVIVOR_BIASED`; it is research evidence, not a
point-in-time universe backtest or promotion evidence.

When `$stock-scenario-story` will run next, save the unmodified JSON output to a file. That downstream skill requires `source_skill`, `result_schema`, `method_version`, and the complete calculator payload; do not summarize or reconstruct the handoff manually.

## Output boundaries
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
interface:
display_name: "Quant Stock Technical"
short_description: "Four-exchange EOD acquisition and screening"
default_prompt: "Use $quant-stock-technical to acquire resumable read-only KIS Korean and U.S. adjusted-EOD bundles, calculate reproducible technical scores, or build and screen a frozen KOSPI, KOSDAQ, NYSE, and NASDAQ universe."
short_description: "Four-exchange screening and opening-hour research"
default_prompt: "Use $quant-stock-technical to acquire read-only KIS EOD data, calculate reproducible technical scores, screen a frozen four-exchange universe, or evaluate selected opening-hour outcomes."
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,14 @@ def atr_adx(bars: list[Bar], period: int = 14) -> tuple[list[Optional[float]], l
minus_di[index] = 100.0 * minus_value / atr_value
denominator = plus_di[index] + minus_di[index]
dx[index] = 0.0 if denominator == 0 else 100.0 * abs(plus_di[index] - minus_di[index]) / denominator
else:
# A newly listed or previously suspended instrument can begin with
# a flat true-range seed. Wilder's directional movement is zero
# in that case; leaving DX unavailable would prevent ADX from ever
# initializing, even after the instrument starts trading.
plus_di[index] = 0.0
minus_di[index] = 0.0
dx[index] = 0.0

first_adx = 2 * period - 1
initial_dx = [value for value in dx[period : first_adx + 1] if value is not None]
Expand Down Expand Up @@ -459,7 +467,10 @@ def calculate(ticker_bars: list[Bar], benchmark_bars: list[Bar], market: str, ti
percentiles: dict[str, float] = {}
reference_counts: dict[str, int] = {}
for name, series in {**features, **risk_features}.items():
percentiles[name], reference_counts[name] = percentile_rank(series, index)
try:
percentiles[name], reference_counts[name] = percentile_rank(series, index)
except BlockedError as exc:
raise BlockedError(f"{name}: {exc}") from exc

short_weights = {
"return_5": 0.25,
Expand Down Expand Up @@ -600,6 +611,20 @@ def synthetic_bars(length: int, drift: float, phase: float) -> list[Bar]:
def self_test() -> None:
ticker_bars = synthetic_bars(1100, 0.0006, 0.0)
benchmark_bars = synthetic_bars(1100, 0.0003, 1.0)
flat_then_active = [
Bar(
day=date(2020, 1, 1) + timedelta(days=index),
open=100.0 if index < 20 else 100.0 + index - 20,
high=100.0 if index < 20 else 101.0 + index - 20,
low=100.0 if index < 20 else 99.0 + index - 20,
close=100.0 if index < 20 else 100.5 + index - 20,
volume=0.0 if index < 20 else 1_000.0,
)
for index in range(80)
]
_, restarted_adx, _, _ = atr_adx(flat_then_active, 14)
assert restarted_adx[-1] is not None
assert math.isfinite(restarted_adx[-1])
with tempfile.TemporaryDirectory(prefix="qta-self-test-") as directory:
paths = [Path(directory) / "ticker.csv", Path(directory) / "benchmark.csv"]
for path, bars in zip(paths, (ticker_bars, benchmark_bars)):
Expand Down
Loading
Loading