Skip to content

Commit f9efb16

Browse files
Pigbibicursoragent
andauthored
Add dividend quality dry-run fixtures and end-to-end smoke path. (#2)
Includes committed market-history and snapshot fixtures, builder/smoke scripts, dividend dry-run tests, and CI checkout for CnEquitySnapshotPipelines. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 94cd391 commit f9efb16

13 files changed

Lines changed: 4247 additions & 5 deletions

.env.example

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ STRATEGY_PROFILE=cn_index_etf_tactical_rotation
33
ACCOUNT_PREFIX=QMT
44
ACCOUNT_REGION=CN
55
QMT_MARKET_HISTORY_PATH=data/fixtures/market_history.sample.csv
6-
QMT_FEATURE_SNAPSHOT_PATH=
7-
QMT_FEATURE_SNAPSHOT_MANIFEST_PATH=
6+
QMT_FEATURE_SNAPSHOT_PATH=data/fixtures/dividend_quality/cn_dividend_quality_snapshot_factor_snapshot_latest.csv
7+
QMT_FEATURE_SNAPSHOT_MANIFEST_PATH=data/fixtures/dividend_quality/cn_dividend_quality_snapshot_factor_snapshot_latest.csv.manifest.json

.github/workflows/ci.yml

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,19 @@ jobs:
4242
done
4343
echo "ref=${ref}" >> "$GITHUB_OUTPUT"
4444
45+
- name: Resolve CnEquitySnapshotPipelines ref
46+
id: cn-equity-snapshot-pipelines-ref
47+
run: |
48+
set -euo pipefail
49+
ref="main"
50+
for candidate in "${GITHUB_HEAD_REF:-}" "${GITHUB_BASE_REF:-}"; do
51+
if [ -n "$candidate" ] && git ls-remote --exit-code --heads https://github.com/QuantStrategyLab/CnEquitySnapshotPipelines.git "$candidate" >/dev/null 2>&1; then
52+
ref="$candidate"
53+
break
54+
fi
55+
done
56+
echo "ref=${ref}" >> "$GITHUB_OUTPUT"
57+
4558
- name: Checkout QuantPlatformKit
4659
uses: actions/checkout@v6
4760
with:
@@ -56,6 +69,13 @@ jobs:
5669
ref: ${{ steps.cn-equity-strategies-ref.outputs.ref }}
5770
path: external/CnEquityStrategies
5871

72+
- name: Checkout CnEquitySnapshotPipelines
73+
uses: actions/checkout@v6
74+
with:
75+
repository: QuantStrategyLab/CnEquitySnapshotPipelines
76+
ref: ${{ steps.cn-equity-snapshot-pipelines-ref.outputs.ref }}
77+
path: external/CnEquitySnapshotPipelines
78+
5979
- name: Setup Python
6080
uses: actions/setup-python@v6
6181
with:
@@ -66,7 +86,7 @@ jobs:
6686
set -euo pipefail
6787
python -m pip install --upgrade pip
6888
python -m pip install -e '.[test]' ruff
69-
python -m pip install --no-deps -e external/QuantPlatformKit -e external/CnEquityStrategies
89+
python -m pip install --no-deps -e external/QuantPlatformKit -e external/CnEquityStrategies -e external/CnEquitySnapshotPipelines
7090
7191
- name: Run ruff
7292
run: python -m ruff check . --extend-exclude external

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ __pycache__/
66
dist/
77
build/
88
.DS_Store
9-
data/
9+
data/*
10+
!data/fixtures/
11+
!data/fixtures/**

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ Current scope is **dry-run first**: evaluate strategy targets and preview orders
1313

1414
## Quick start
1515

16+
### ETF tactical rotation (market history)
17+
1618
```bash
1719
python3 -m pip install -e '.[test]'
1820
python3 -m pip install --no-deps -e ../QuantPlatformKit ../CnEquityStrategies
@@ -26,6 +28,29 @@ curl http://127.0.0.1:8080/probe
2628
curl http://127.0.0.1:8080/dry-run
2729
```
2830

31+
### Dividend quality snapshot (feature snapshot)
32+
33+
```bash
34+
python3 -m pip install --no-deps -e ../CnEquitySnapshotPipelines
35+
36+
# Regenerate fixtures (uses sample factor CSV; sets as_of to today)
37+
python3 scripts/build_fixtures.py
38+
39+
export STRATEGY_PROFILE=cn_dividend_quality_snapshot
40+
export QMT_DRY_RUN_ONLY=true
41+
export QMT_FEATURE_SNAPSHOT_PATH=data/fixtures/dividend_quality/cn_dividend_quality_snapshot_factor_snapshot_latest.csv
42+
export QMT_FEATURE_SNAPSHOT_MANIFEST_PATH=data/fixtures/dividend_quality/cn_dividend_quality_snapshot_factor_snapshot_latest.csv.manifest.json
43+
44+
python3 main.py
45+
curl http://127.0.0.1:8080/dry-run
46+
```
47+
48+
End-to-end smoke (stage/build/run):
49+
50+
```bash
51+
python3 scripts/smoke_cn_dividend_quality_dry_run_e2e.py
52+
```
53+
2954
## Environment variables
3055

3156
| Variable | Default | Description |
@@ -34,6 +59,7 @@ curl http://127.0.0.1:8080/dry-run
3459
| `STRATEGY_PROFILE` | required | Strategy profile id |
3560
| `QMT_MARKET_HISTORY_PATH` || CSV with `date,symbol,close` for direct strategies |
3661
| `QMT_FEATURE_SNAPSHOT_PATH` || Snapshot CSV for feature-snapshot strategies |
62+
| `QMT_FEATURE_SNAPSHOT_MANIFEST_PATH` || Snapshot manifest JSON (required for dividend quality) |
3763
| `RUNTIME_TARGET_JSON` || Optional runtime target override from QuantRuntimeSettings |
3864

3965
See `.env.example` and `CnEquityStrategies/docs/platform_integration.md`.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
as_of,symbol,sector,close_cny,adv20_cny,market_cap_cny,dividend_yield_ttm,dividend_stability_3y,earnings_positive,payout_ratio,roe_ttm,roe_stability_3y,realized_vol_126,mom_12_1,sma200_gap,suspension_days_63,is_st,list_days
2+
2026-06-27,600519,consumer,1680.0,800000000.0,2000000000000.0,0.035,0.85,True,0.45,0.28,0.8,0.22,0.08,0.05,0,False,4000
3+
2026-06-27,601088,energy,28.0,120000000.0,60000000000.0,0.055,0.78,True,0.55,0.16,0.72,0.18,0.12,0.08,0,False,3000
4+
2026-06-27,1,finance,12.0,200000000.0,230000000000.0,0.048,0.7,True,0.35,0.11,0.65,0.16,0.04,0.03,0,False,8000
5+
2026-06-27,510300,index,4.0,1000000000.0,0.0,0.02,0.5,True,0.0,0.1,0.5,0.14,0.01,0.01,0,False,3000
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"config_name": "cn_dividend_quality_snapshot",
3+
"config_path": null,
4+
"config_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
5+
"contract_version": "cn_dividend_quality_snapshot.factor_snapshot.v1",
6+
"generated_at": "2026-06-27T15:03:17.043212+00:00",
7+
"manifest_type": "feature_snapshot",
8+
"row_count": 4,
9+
"snapshot_as_of": "2026-06-27",
10+
"snapshot_path": "/Users/lisiyi/Projects/QmtPlatform/data/fixtures/dividend_quality/cn_dividend_quality_snapshot_factor_snapshot_latest.csv",
11+
"snapshot_sha256": "ba00a43b18ca204a53f6f657774b2964bc196a6727f329d0f9dd242f36d1cedd",
12+
"source_project": "CnEquitySnapshotPipelines",
13+
"strategy_profile": "cn_dividend_quality_snapshot"
14+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
rank,symbol,sector,score,eligible,close_cny,adv20_cny,market_cap_cny,dividend_yield_ttm,dividend_stability_3y,roe_ttm,roe_stability_3y,realized_vol_126,mom_12_1,sma200_gap
2+
1,601088,energy,0.4369198095556462,True,28.0,120000000.0,60000000000.0,0.055,0.78,0.16,0.72,0.18,0.12,0.08
3+
2,600519,consumer,0.11194564869990552,True,1680.0,800000000.0,2000000000000.0,0.035,0.85,0.28,0.8,0.22,0.08,0.05
4+
3,000001,finance,-0.5488654582555526,True,12.0,200000000.0,230000000000.0,0.048,0.7,0.11,0.65,0.16,0.04,0.03
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"contract_version": "cn_dividend_quality_snapshot.factor_snapshot.v1",
3+
"diagnostics": {
4+
"actionable": true,
5+
"breadth_ratio": 1.0,
6+
"candidate_count": 3,
7+
"managed_symbols": [
8+
"600519",
9+
"601088",
10+
"000001",
11+
"510300"
12+
],
13+
"realized_stock_weight": 0.24,
14+
"regime": "risk_on",
15+
"safe_haven_weight": 0.76,
16+
"selected_count": 3,
17+
"selected_symbols": [
18+
"601088",
19+
"600519",
20+
"000001"
21+
],
22+
"signal_source": "factor_snapshot",
23+
"snapshot_contract_version": "cn_dividend_quality_snapshot.factor_snapshot.v1",
24+
"status_icon": "🇨🇳",
25+
"target_stock_weight": 1.0,
26+
"target_weights": {
27+
"000001": 0.08,
28+
"510300": 0.76,
29+
"600519": 0.08,
30+
"601088": 0.08
31+
}
32+
},
33+
"display_name": "CN Dividend Quality Snapshot",
34+
"generated_at": "2026-06-27T15:03:17.068089+00:00",
35+
"manifest_path": "/Users/lisiyi/Projects/QmtPlatform/data/fixtures/dividend_quality/cn_dividend_quality_snapshot_factor_snapshot_latest.csv.manifest.json",
36+
"ranking_path": "/Users/lisiyi/Projects/QmtPlatform/data/fixtures/dividend_quality/cn_dividend_quality_snapshot_ranking_latest.csv",
37+
"release_status": "ready",
38+
"row_count": 4,
39+
"signal_description": "cn dividend quality regime=risk_on breadth=100.0% target_stock=100.0% selected=3 top=601088(0.44), 600519(0.11), 000001(-0.55)",
40+
"snapshot_as_of": "2026-06-27",
41+
"snapshot_path": "/Users/lisiyi/Projects/QmtPlatform/data/fixtures/dividend_quality/cn_dividend_quality_snapshot_factor_snapshot_latest.csv",
42+
"source_project": "CnEquitySnapshotPipelines",
43+
"status_description": "regime=risk_on | breadth=100.0% | target_stock=100.0%",
44+
"strategy_profile": "cn_dividend_quality_snapshot"
45+
}

0 commit comments

Comments
 (0)