vizflow 0.4.4__py3-none-any.whl → 0.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
vizflow/__init__.py CHANGED
@@ -5,7 +5,7 @@ Usage:
5
5
  import vizflow as vf
6
6
  """
7
7
 
8
- __version__ = "0.4.4"
8
+ __version__ = "0.5.0"
9
9
 
10
10
  from .config import ColumnSchema, Config, get_config, set_config
11
11
  from .io import (
@@ -18,5 +18,5 @@ from .io import (
18
18
  scan_trades,
19
19
  )
20
20
  from .market import CN, CRYPTO, Market, Session
21
- from .ops import aggregate, bin, parse_time
21
+ from .ops import aggregate, bin, forward_return, parse_time
22
22
  from .presets import JYAO_V20251114, PRESETS, YLIN_V20251204
vizflow/ops.py CHANGED
@@ -135,3 +135,95 @@ def aggregate(
135
135
  """
136
136
  agg_exprs = [expr.alias(name) for name, expr in metrics.items()]
137
137
  return df.group_by(group_by).agg(agg_exprs)
138
+
139
+
140
+ def _horizon_to_suffix(horizon_seconds: int) -> str:
141
+ """Convert horizon in seconds to column name suffix.
142
+
143
+ Rule: ≤60s → use seconds (60s), >60s → use minutes (3m, 30m)
144
+ """
145
+ if horizon_seconds <= 60:
146
+ return f"{horizon_seconds}s"
147
+ else:
148
+ minutes = horizon_seconds // 60
149
+ return f"{minutes}m"
150
+
151
+
152
+ def forward_return(
153
+ df_trade: pl.LazyFrame,
154
+ df_alpha: pl.LazyFrame,
155
+ horizons: list[int],
156
+ trade_time_col: str = "elapsed_alpha_ts",
157
+ alpha_time_col: str = "elapsed_ticktime",
158
+ price_col: str = "mid",
159
+ symbol_col: str = "ukey",
160
+ ) -> pl.LazyFrame:
161
+ """Merge alpha's future price to trade and calculate forward returns.
162
+
163
+ For each trade row:
164
+ 1. Look up alpha price at trade_time + horizon
165
+ 2. Add forward_{price_col}_{horizon} column (the future price)
166
+ 3. Calculate y_{horizon} = (forward_price - current_price) / current_price
167
+
168
+ Output column names follow the convention:
169
+ - ≤60s → forward_mid_60s, y_60s
170
+ - >60s → forward_mid_3m, y_3m
171
+
172
+ Args:
173
+ df_trade: Trade LazyFrame with trade_time_col and price_col
174
+ df_alpha: Alpha LazyFrame with alpha_time_col and price_col
175
+ horizons: List of horizon in seconds, e.g., [60, 180, 1800]
176
+ trade_time_col: Time column in trade df (default: "elapsed_alpha_ts")
177
+ alpha_time_col: Time column in alpha df (default: "elapsed_ticktime")
178
+ price_col: Column name for price in both dfs (default: "mid")
179
+ symbol_col: Symbol column for grouping (default: "ukey")
180
+
181
+ Returns:
182
+ Trade LazyFrame with forward_* and y_* columns added
183
+
184
+ Example:
185
+ >>> df_trade = vf.parse_time(vf.scan_trade(date), "alpha_ts")
186
+ >>> df_alpha = vf.parse_time(vf.scan_alpha(date), "ticktime")
187
+ >>> df = vf.forward_return(df_trade, df_alpha, horizons=[60, 180, 1800])
188
+ >>> # Creates: forward_mid_60s, forward_mid_3m, forward_mid_30m
189
+ >>> # y_60s, y_3m, y_30m
190
+ """
191
+ # Collect for asof join
192
+ trade = df_trade.collect()
193
+ alpha = df_alpha.collect()
194
+
195
+ # Prepare alpha lookup table: (symbol, time) -> price
196
+ alpha_lookup = alpha.select([
197
+ pl.col(symbol_col),
198
+ pl.col(alpha_time_col),
199
+ pl.col(price_col),
200
+ ]).sort([symbol_col, alpha_time_col])
201
+
202
+ for horizon in horizons:
203
+ suffix = _horizon_to_suffix(horizon)
204
+ horizon_ms = horizon * 1000
205
+ forward_col = f"forward_{price_col}_{suffix}"
206
+ return_col = f"y_{suffix}"
207
+
208
+ # Add target time column for this horizon
209
+ trade = trade.with_columns(
210
+ (pl.col(trade_time_col) + horizon_ms).alias("_forward_time")
211
+ )
212
+
213
+ # Asof join: find alpha price at forward_time
214
+ joined = trade.join_asof(
215
+ alpha_lookup.rename({alpha_time_col: "_alpha_time", price_col: "_forward_price"}),
216
+ left_on="_forward_time",
217
+ right_on="_alpha_time",
218
+ by=symbol_col,
219
+ strategy="nearest",
220
+ tolerance=1000, # 1 second tolerance
221
+ )
222
+
223
+ # Add forward price and calculate return
224
+ trade = joined.with_columns([
225
+ pl.col("_forward_price").alias(forward_col),
226
+ ((pl.col("_forward_price") - pl.col(price_col)) / pl.col(price_col)).alias(return_col),
227
+ ]).drop(["_forward_time", "_alpha_time", "_forward_price"])
228
+
229
+ return trade.lazy()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vizflow
3
- Version: 0.4.4
3
+ Version: 0.5.0
4
4
  Requires-Python: >=3.9
5
5
  Requires-Dist: polars>=0.20.0
6
6
  Provides-Extra: dev
@@ -1,10 +1,10 @@
1
- vizflow/__init__.py,sha256=vYhGrFOQoONxBA6TJ08OQwWFd_UzltTsoZNQryNwnko,480
1
+ vizflow/__init__.py,sha256=ZIMYQ-Yzh3eEAd7MSqNA00SlSuj45bEE6NsXM9Qc6O0,496
2
2
  vizflow/config.py,sha256=zSZnhdHzgXSqhDenHcHKm4CDGrMpKAdkNNRoUYYF1uc,6530
3
3
  vizflow/io.py,sha256=zmN0fFQOTmSBEBKangMExr0Q5mC2gajZM6GgdAyWkw4,8824
4
4
  vizflow/market.py,sha256=MtNz_nnZxC66Aq-i2PXEwaFCTknijFWYZUUv6798k2s,2493
5
- vizflow/ops.py,sha256=NL-Gtv-m_O1hv-0RUb9Wt43916HsQ5tYK_0e_uKR90w,4062
5
+ vizflow/ops.py,sha256=6hKOjJowFrw1b6z4y8Liea9KTp8Fgy6kCGPZ6t15PVk,7426
6
6
  vizflow/presets.py,sha256=h91NZoOH4YAx0bbsaNigECf9WOcWh1QZavguunWkaLE,2452
7
7
  vizflow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- vizflow-0.4.4.dist-info/METADATA,sha256=NxMcTJ5fQKbB6GPak9dHARYTp9h0WwcDwxQAhrHcxRU,388
9
- vizflow-0.4.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
10
- vizflow-0.4.4.dist-info/RECORD,,
8
+ vizflow-0.5.0.dist-info/METADATA,sha256=cIIvBPZo2U6Sp46Wxgyu_tCVPWF4DGsgvapbavEBGl8,388
9
+ vizflow-0.5.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
10
+ vizflow-0.5.0.dist-info/RECORD,,