271 lines
10 KiB
Python
271 lines
10 KiB
Python
import hashlib
|
|
import json
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0, str(ROOT))
|
|
sys.path.insert(0, str(ROOT / "src"))
|
|
|
|
from platforms import joinquant_strategy, qmt_builtin_strategy
|
|
from quant60.target_package import seal_target_package
|
|
from tools.bundle_platforms import bundle_all, effective_platform_config
|
|
from tools.capability_probe import probe_capabilities
|
|
|
|
|
|
def target_package():
|
|
return seal_target_package(
|
|
{
|
|
"schema_version": "1.0",
|
|
"package_type": "TargetPackageV1",
|
|
"package_id": "TP-20260724-bundle",
|
|
"decision_id": "D-20260724-bundle",
|
|
"release": "quant60-research-candidate-v1",
|
|
"evidence_class": "synthetic-research",
|
|
"model_id": "deterministic-ridge-alpha-5",
|
|
"signal_as_of": "2026-07-24T15:00:00+08:00",
|
|
"next_session": "2026-07-27",
|
|
"model_sha256": "1" * 64,
|
|
"data_sha256": "2" * 64,
|
|
"feature_sha256": "3" * 64,
|
|
"risk_sha256": "4" * 64,
|
|
"cost_sha256": "5" * 64,
|
|
"optimizer_sha256": "6" * 64,
|
|
"config_sha256": "7" * 64,
|
|
"source_sha256": "8" * 64,
|
|
"target_weights": {
|
|
"000001.XSHE": 0.30,
|
|
"600000.XSHG": 0.20,
|
|
},
|
|
"universe": {
|
|
"000001.XSHE": {
|
|
"state": "openable",
|
|
"reasons": ["ELIGIBLE"],
|
|
},
|
|
"600000.XSHG": {
|
|
"state": "openable",
|
|
"reasons": ["ELIGIBLE"],
|
|
},
|
|
},
|
|
"constraints": {
|
|
"constraint_state": "FEASIBLE",
|
|
"long_only": True,
|
|
"max_single_weight": 0.40,
|
|
"max_gross_weight": 0.80,
|
|
"max_one_way_turnover": 0.50,
|
|
"actual_gross_weight": 0.50,
|
|
},
|
|
}
|
|
)
|
|
|
|
|
|
class BundleTest(unittest.TestCase):
|
|
def test_source_wrappers_match_canonical_baseline_config(self):
|
|
baseline = json.loads(
|
|
(ROOT / "configs/baseline.json").read_text(encoding="utf-8")
|
|
)
|
|
self.assertEqual(
|
|
joinquant_strategy.CONFIG,
|
|
effective_platform_config(baseline, "joinquant"),
|
|
)
|
|
self.assertEqual(
|
|
qmt_builtin_strategy.CONFIG,
|
|
effective_platform_config(baseline, "qmt_builtin"),
|
|
)
|
|
|
|
def test_bundles_inline_same_core_compile_and_match_manifest(self):
|
|
with tempfile.TemporaryDirectory() as temp:
|
|
output = Path(temp)
|
|
manifest = bundle_all(ROOT, output)
|
|
manifest_file = output / "bundle_manifest.json"
|
|
stored = json.loads(manifest_file.read_text(encoding="ascii"))
|
|
for name, filename in {
|
|
"joinquant": "joinquant_strategy.py",
|
|
"qmt_builtin": "qmt_builtin_strategy.py",
|
|
}.items():
|
|
artifact = output / filename
|
|
payload = artifact.read_bytes()
|
|
compile(payload, str(artifact), "exec")
|
|
self.assertNotIn(b"from quant60.portable_core import", payload)
|
|
self.assertEqual(
|
|
hashlib.sha256(payload).hexdigest(),
|
|
stored["artifacts"][name]["output_sha256"],
|
|
)
|
|
(output / "qmt_builtin_strategy.py").read_bytes().decode("ascii")
|
|
self.assertEqual(
|
|
stored["artifacts"]["joinquant"]["core"],
|
|
"src/quant60/portable_core.py",
|
|
)
|
|
self.assertNotIn(
|
|
"/Users/", json.dumps(stored, ensure_ascii=True)
|
|
)
|
|
self.assertEqual(
|
|
stored["portable_core_sha256"],
|
|
manifest["portable_core_sha256"],
|
|
)
|
|
self.assertEqual(stored["baseline_config"], "configs/baseline.json")
|
|
self.assertEqual(
|
|
stored["baseline_config_sha256"],
|
|
hashlib.sha256(
|
|
(ROOT / "configs/baseline.json").read_bytes()
|
|
).hexdigest(),
|
|
)
|
|
self.assertEqual(
|
|
stored["decision_mode"],
|
|
"portable_momentum_smoke",
|
|
)
|
|
self.assertEqual(stored["target_package_count"], 0)
|
|
self.assertIsNone(stored["target_package_tape_sha256"])
|
|
self.assertEqual(
|
|
stored["joinquant_observation"]["prefix"],
|
|
"QUANT60_JOINQUANT_EVIDENCE_V1 ",
|
|
)
|
|
self.assertTrue(
|
|
stored["joinquant_observation"]["fail_soft"]
|
|
)
|
|
self.assertEqual(
|
|
stored["joinquant_observation"]["target_price_source"],
|
|
"CURRENT_DATA_DAY_OPEN",
|
|
)
|
|
self.assertEqual(
|
|
stored["joinquant_observation"]["eod_chunk_encoding"],
|
|
"base64-canonical-json",
|
|
)
|
|
self.assertEqual(
|
|
stored["joinquant_observation"]["eod_chunk_characters"],
|
|
1800,
|
|
)
|
|
self.assertIn(
|
|
"EOD_STATUS",
|
|
stored["joinquant_observation"]["events"],
|
|
)
|
|
|
|
def test_committed_dist_is_byte_for_byte_fresh(self):
|
|
with tempfile.TemporaryDirectory() as temp:
|
|
output = Path(temp)
|
|
bundle_all(ROOT, output)
|
|
for name in (
|
|
"joinquant_strategy.py",
|
|
"qmt_builtin_strategy.py",
|
|
"bundle_manifest.json",
|
|
):
|
|
self.assertEqual(
|
|
(ROOT / "dist" / name).read_bytes(),
|
|
(output / name).read_bytes(),
|
|
f"committed dist artifact is stale: {name}",
|
|
)
|
|
|
|
def test_joinquant_bundle_ignores_host_shadowed_sum_name(self):
|
|
with tempfile.TemporaryDirectory() as temp:
|
|
output = Path(temp)
|
|
bundle_all(ROOT, output)
|
|
source = (output / "joinquant_strategy.py").read_text(
|
|
encoding="utf-8"
|
|
)
|
|
namespace = {"sum": lambda values: values}
|
|
exec(compile(source, "joinquant_strategy.py", "exec"), namespace)
|
|
weights = namespace["capped_target_weights"](
|
|
{
|
|
"600000.XSHG": 3.0,
|
|
"000001.XSHE": 2.0,
|
|
"300750.XSHE": 1.0,
|
|
},
|
|
max_weight=0.4,
|
|
gross_target=0.95,
|
|
)
|
|
self.assertAlmostEqual(
|
|
namespace["_sum_numeric"](weights.values()),
|
|
0.95,
|
|
)
|
|
quantities = namespace["target_quantities"](
|
|
weights,
|
|
{symbol: 10.0 for symbol in weights},
|
|
equity=1_000_000,
|
|
cash_buffer=0.02,
|
|
)
|
|
self.assertTrue(all(value >= 0 for value in quantities.values()))
|
|
|
|
def test_target_package_bundle_is_explicit_pinned_and_no_fallback(self):
|
|
with tempfile.TemporaryDirectory() as temp:
|
|
root = Path(temp)
|
|
package_path = root / "target_package.json"
|
|
package = target_package()
|
|
package_path.write_text(
|
|
json.dumps(package, ensure_ascii=False),
|
|
encoding="utf-8",
|
|
)
|
|
output = root / "bundle"
|
|
manifest = bundle_all(ROOT, output, package_path)
|
|
self.assertEqual(manifest["decision_mode"], "target_package")
|
|
self.assertEqual(manifest["target_package_count"], 1)
|
|
self.assertEqual(
|
|
manifest["target_package_ids"],
|
|
[package["package_id"]],
|
|
)
|
|
self.assertEqual(
|
|
manifest["target_package_sha256"],
|
|
[package["package_sha256"]],
|
|
)
|
|
self.assertNotIn(
|
|
str(root),
|
|
json.dumps(manifest, ensure_ascii=False),
|
|
)
|
|
for filename in (
|
|
"joinquant_strategy.py",
|
|
"qmt_builtin_strategy.py",
|
|
):
|
|
source = (output / filename).read_text(encoding="utf-8")
|
|
self.assertIn(
|
|
"'decision_mode': 'target_package'",
|
|
source,
|
|
)
|
|
self.assertNotIn("TARGET_PACKAGES = []", source)
|
|
self.assertIn(package["package_sha256"], source)
|
|
self.assertIn("build_target_weight_plan", source)
|
|
joinquant_source = (
|
|
output / "joinquant_strategy.py"
|
|
).read_text(encoding="utf-8")
|
|
self.assertIn(
|
|
"QUANT60_JOINQUANT_EVIDENCE_V1 ",
|
|
joinquant_source,
|
|
)
|
|
self.assertIn("CURRENT_DATA_DAY_OPEN", joinquant_source)
|
|
self.assertIn("day_open", joinquant_source)
|
|
self.assertNotIn("CURRENT_DATA_LAST_PRICE", joinquant_source)
|
|
for event in manifest["joinquant_observation"]["events"]:
|
|
self.assertIn(event, joinquant_source)
|
|
|
|
tampered = dict(package)
|
|
tampered["release"] = "tampered"
|
|
package_path.write_text(
|
|
json.dumps(tampered),
|
|
encoding="utf-8",
|
|
)
|
|
with self.assertRaisesRegex(ValueError, "hash mismatch"):
|
|
bundle_all(ROOT, root / "tampered", package_path)
|
|
|
|
|
|
class CapabilityProbeTest(unittest.TestCase):
|
|
def test_shallow_probe_does_not_claim_external_verification(self):
|
|
report = probe_capabilities(ROOT, deep=False)
|
|
self.assertTrue(report["artifacts"]["portable_core"])
|
|
self.assertTrue(report["artifacts"]["colab_notebook"])
|
|
self.assertTrue(report["artifacts"]["jqdata_snapshot_adapter"])
|
|
self.assertTrue(report["artifacts"]["tushare_qlib_adapter"])
|
|
self.assertTrue(report["artifacts"]["tushare_qlib_cli"])
|
|
self.assertTrue(report["artifacts"]["qmt_shadow_planner"])
|
|
self.assertTrue(report["artifacts"]["qmt_shadow_cli"])
|
|
self.assertIn("no external platform", report["verification_boundary"])
|
|
self.assertTrue(report["matrix"]["xttrader"]["safe_default"])
|
|
self.assertIn("rejects BJ", report["matrix"]["xttrader"]["market_scope"])
|
|
self.assertTrue(report["matrix"]["tushare_local_qlib"]["safe_default"])
|
|
for probe in report["optional_runtimes"].values():
|
|
self.assertIs(probe["import_ok"], None)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|