docs: add quantitative guide, update README + CHANGELOG, bump v1.11.1

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
GitHub
2026-06-12 22:12:19 +08:00
co-authored by Claude
parent bfefadf70b
commit a6ed0eac16
11 changed files with 3338 additions and 11 deletions
-1
View File
@@ -4,7 +4,6 @@ from __future__ import annotations
import numpy as np
import pandas as pd
import pytest
from easy_tdx.factor.analysis import FactorAnalyzer, FactorReport
-1
View File
@@ -4,7 +4,6 @@ from __future__ import annotations
import numpy as np
import pandas as pd
import pytest
from easy_tdx.factor.transform import (
fill_missing,
+5 -1
View File
@@ -57,7 +57,11 @@ class TestRiskParity:
assert abs(sum(w.values()) - 1.0) < 1e-6
def test_with_volatility_column(self):
scores = pd.DataFrame({"code": ["A", "B", "C"], "score": [1.0, 1.0, 1.0], "volatility": [0.1, 0.2, 0.4]})
scores = pd.DataFrame({
"code": ["A", "B", "C"],
"score": [1.0, 1.0, 1.0],
"volatility": [0.1, 0.2, 0.4],
})
w = RiskParityOptimizer().optimize(scores, n_stocks=3)
assert w["A"] > w["C"]
+15 -5
View File
@@ -3,7 +3,6 @@ from __future__ import annotations
import numpy as np
import pandas as pd
import pytest
from easy_tdx.portfolio.optimizer import EqualWeightOptimizer, FactorWeightedOptimizer
from easy_tdx.portfolio.rebalance import RebalanceEngine
@@ -27,7 +26,11 @@ def _make_market(n_stocks: int = 10, n_days: int = 120, seed: int = 42) -> dict[
class TestRebalanceEngine:
def test_basic_run(self):
engine = RebalanceEngine(optimizer=EqualWeightOptimizer(), factor_name="momentum_20d", n_stocks=5, rebalance_freq="M", cash=1_000_000)
engine = RebalanceEngine(
optimizer=EqualWeightOptimizer(),
factor_name="momentum_20d", n_stocks=5,
rebalance_freq="M", cash=1_000_000,
)
result = engine.run(_make_market(), start_date=20240101, end_date=20240430)
assert len(result.states) > 0
assert len(result.rebalance_dates) > 0
@@ -35,7 +38,10 @@ class TestRebalanceEngine:
assert "total_return" in result.performance
def test_with_factor_weighted(self):
engine = RebalanceEngine(optimizer=FactorWeightedOptimizer(), factor_name="momentum_20d", n_stocks=5)
engine = RebalanceEngine(
optimizer=FactorWeightedOptimizer(),
factor_name="momentum_20d", n_stocks=5,
)
result = engine.run(_make_market(), start_date=20240101, end_date=20240430)
assert len(result.states) > 0
@@ -44,12 +50,16 @@ class TestRebalanceEngine:
assert result.performance["total_return"] == 0.0
def test_equity_curve_dates_sorted(self):
result = RebalanceEngine(optimizer=EqualWeightOptimizer(), rebalance_freq="M").run(_make_market(), start_date=20240101, end_date=20240430)
result = RebalanceEngine(
optimizer=EqualWeightOptimizer(), rebalance_freq="M",
).run(_make_market(), start_date=20240101, end_date=20240430)
dates = result.equity_curve["datetime"].tolist()
assert dates == sorted(dates)
def test_trades_recorded(self):
engine = RebalanceEngine(optimizer=EqualWeightOptimizer(), n_stocks=3, rebalance_freq="M")
engine = RebalanceEngine(
optimizer=EqualWeightOptimizer(), n_stocks=3, rebalance_freq="M",
)
result = engine.run(_make_market(), start_date=20240101, end_date=20240430)
assert len(result.trades) > 0
assert "BUY" in result.trades["direction"].values