feat(factor): data_adapter 补 vwap 派生列(turnover/volume,零量置null)——Alpha101 表达式 59 处引用 vwap,dbbardata 无此列 [vps]
This commit is contained in:
@@ -18,12 +18,13 @@ def convert_bars_to_alpha_df(bars: list[BarData]) -> pl.DataFrame:
|
||||
bars: List of BarData objects from Phase 1 read_db_daily
|
||||
|
||||
Returns:
|
||||
polars DataFrame with columns: vt_symbol, datetime, open, high, low, close, volume, turnover, open_interest
|
||||
polars DataFrame with columns: vt_symbol, datetime, open, high, low, close, volume, turnover, open_interest, vwap
|
||||
|
||||
Note:
|
||||
SPIKE CORRECTION: AlphaLab.save_bar_data stores parquet columns as
|
||||
datetime, vt_symbol, open, high, low, close, volume, turnover, open_interest
|
||||
(NOT open_price, close_price - this was corrected in S1 spike testing)
|
||||
vwap: turnover/volume 派生(volume=0 置null),Alpha101 表达式依赖
|
||||
"""
|
||||
if not bars:
|
||||
return pl.DataFrame(schema={
|
||||
@@ -36,6 +37,7 @@ def convert_bars_to_alpha_df(bars: list[BarData]) -> pl.DataFrame:
|
||||
"volume": pl.Float64,
|
||||
"turnover": pl.Float64,
|
||||
"open_interest": pl.Float64,
|
||||
"vwap": pl.Float64,
|
||||
})
|
||||
|
||||
return pl.DataFrame({
|
||||
@@ -48,6 +50,7 @@ def convert_bars_to_alpha_df(bars: list[BarData]) -> pl.DataFrame:
|
||||
"volume": [float(b.volume) for b in bars],
|
||||
"turnover": [float(b.turnover) if b.turnover is not None else 0.0 for b in bars],
|
||||
"open_interest": [float(b.open_interest) if b.open_interest is not None else 0.0 for b in bars],
|
||||
"vwap": [(b.turnover / b.volume) if (b.turnover and b.volume) else None for b in bars],
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ def test_convert_empty_bars():
|
||||
|
||||
assert df.height == 0
|
||||
# Should still have schema defined
|
||||
assert len(df.columns) == 9 # vt_symbol, datetime, open, high, low, close, volume, turnover, open_interest
|
||||
assert len(df.columns) == 10 # vt_symbol, datetime, open, high, low, close, volume, turnover, open_interest, vwap
|
||||
|
||||
|
||||
def test_save_alpha_lab_data():
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
"""vwap 派生列:turnover/volume,volume=0 → null."""
|
||||
import sys, os
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")))
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "vnpy_v4.4.0")))
|
||||
|
||||
from datetime import datetime
|
||||
from vnpy.trader.object import BarData
|
||||
from vnpy.trader.constant import Exchange, Interval
|
||||
from sanguo_factor.data_adapter import convert_bars_to_alpha_df
|
||||
|
||||
|
||||
def _bar(symbol, dt, close=10.0, volume=100.0, turnover=1000.0):
|
||||
return BarData(
|
||||
symbol=symbol, exchange=Exchange.SSE, datetime=dt, interval=Interval.DAILY,
|
||||
open_price=9.9, high_price=10.1, low_price=9.8, close_price=close,
|
||||
volume=volume, turnover=turnover, open_interest=0, gateway_name="T",
|
||||
)
|
||||
|
||||
|
||||
def test_vwap_derived():
|
||||
df = convert_bars_to_alpha_df([_bar("600000", datetime(2024, 1, 5))])
|
||||
assert df["vwap"][0] == 10.0 # 1000 / 100
|
||||
|
||||
|
||||
def test_vwap_null_when_volume_zero():
|
||||
df = convert_bars_to_alpha_df([_bar("600000", datetime(2024, 1, 5), volume=0.0, turnover=0.0)])
|
||||
assert df["vwap"][0] is None
|
||||
|
||||
|
||||
def test_empty_schema_has_vwap():
|
||||
df = convert_bars_to_alpha_df([])
|
||||
assert "vwap" in df.columns
|
||||
assert df.height == 0
|
||||
Reference in New Issue
Block a user