Add synthetic taker flow, timestamps, open interest, and metadata to indicator harness; improve error messages and theme tweaks
- Generate buy/sell volume split with random fractions - Add nanosecond timestamps for OHLC extremes within 1-minute bars - Include open interest as separate random walk - Add num_trades and quote_volume derived fields - Derive extra_columns dynamically from indicator input requirements instead of hardcoded volume check - Improve input_series error message clarity - Adjust ChatPanel background color for user messages
This commit is contained in:
@@ -179,7 +179,10 @@ async def evaluate_indicator(
|
||||
|
||||
# Determine required columns
|
||||
input_cols = _INPUTS.get(name_lower, ("close",))
|
||||
needs_volume = "volume" in input_cols
|
||||
|
||||
# Derive extra_columns from whatever the indicator actually needs
|
||||
_STANDARD_OHLC = {"open", "high", "low", "close"}
|
||||
extra_columns = [col for col in input_cols if col not in _STANDARD_OHLC]
|
||||
|
||||
# Fetch OHLC
|
||||
try:
|
||||
@@ -190,7 +193,7 @@ async def evaluate_indicator(
|
||||
period_seconds=period_seconds,
|
||||
start_time=from_time,
|
||||
end_time=to_time,
|
||||
extra_columns=["volume"] if needs_volume else [],
|
||||
extra_columns=extra_columns,
|
||||
)
|
||||
except Exception as exc:
|
||||
log.exception("evaluate_indicator: OHLC fetch failed")
|
||||
|
||||
@@ -36,9 +36,9 @@ def make_synthetic_ohlcv(n: int = 200):
|
||||
|
||||
rng = np.random.default_rng(42)
|
||||
|
||||
# Realistic BTC-style price random walk
|
||||
returns = rng.normal(0, 0.015, n)
|
||||
closes = 40_000.0 * np.cumprod(1.0 + returns)
|
||||
# Realistic BTC-style price random walk (log-normal GBM — always positive)
|
||||
log_returns = rng.normal(0, 0.015, n)
|
||||
closes = 40_000.0 * np.exp(np.cumsum(log_returns))
|
||||
|
||||
opens = np.empty(n)
|
||||
opens[0] = closes[0]
|
||||
@@ -49,12 +49,43 @@ def make_synthetic_ohlcv(n: int = 200):
|
||||
lows = np.minimum(opens, closes) * (1.0 - noise)
|
||||
volumes = rng.uniform(1e6, 1e8, n)
|
||||
|
||||
# Taker flow: randomly split volume into buy/sell side
|
||||
buy_frac = rng.uniform(0.2, 0.8, n)
|
||||
buy_vols = volumes * buy_frac
|
||||
sell_vols = volumes - buy_vols
|
||||
|
||||
# Synthetic bar timestamps (1-minute bars starting 2024-01-01 UTC, in nanoseconds)
|
||||
bar_ns = 60 * 1_000_000_000
|
||||
epoch_start = 1_704_067_200_000_000_000 # 2024-01-01 00:00:00 UTC in ns
|
||||
bar_starts = epoch_start + np.arange(n) * bar_ns
|
||||
# Each extreme occurs at a random point within its bar
|
||||
open_times = bar_starts + rng.integers(0, bar_ns, n)
|
||||
high_times = bar_starts + rng.integers(0, bar_ns, n)
|
||||
low_times = bar_starts + rng.integers(0, bar_ns, n)
|
||||
close_times = bar_starts + rng.integers(0, bar_ns, n)
|
||||
|
||||
# Futures open interest: separate slow random walk (log-normal — always positive)
|
||||
oi_log_returns = rng.normal(0, 0.003, n)
|
||||
open_interest = 5e8 * np.exp(np.cumsum(oi_log_returns))
|
||||
|
||||
num_trades = rng.integers(500, 5000, n).astype(float)
|
||||
quote_volume = closes * volumes
|
||||
|
||||
return pd.DataFrame({
|
||||
"open": opens,
|
||||
"high": highs,
|
||||
"low": lows,
|
||||
"close": closes,
|
||||
"volume": volumes,
|
||||
"buy_vol": buy_vols,
|
||||
"sell_vol": sell_vols,
|
||||
"open_time": open_times.astype(float),
|
||||
"high_time": high_times.astype(float),
|
||||
"low_time": low_times.astype(float),
|
||||
"close_time": close_times.astype(float),
|
||||
"open_interest": open_interest,
|
||||
"num_trades": num_trades,
|
||||
"quote_volume": quote_volume,
|
||||
})
|
||||
|
||||
|
||||
@@ -175,7 +206,13 @@ def run(impl_path: Path, metadata_path: Path) -> dict:
|
||||
args = []
|
||||
for col in input_series:
|
||||
if col not in df.columns:
|
||||
return {"success": False, "error": f"input_series '{col}' not in synthetic df columns {list(df.columns)}"}
|
||||
return {
|
||||
"success": False,
|
||||
"error": (
|
||||
f"input_series '{col}' is not a valid OHLC column. "
|
||||
f"Available columns: {list(df.columns)}"
|
||||
),
|
||||
}
|
||||
args.append(df[col])
|
||||
|
||||
# --- Execute ---
|
||||
|
||||
@@ -601,7 +601,7 @@ const chatStyles = {
|
||||
},
|
||||
message: {
|
||||
background: '#141414',
|
||||
backgroundMe: '#089981',
|
||||
backgroundMe: '#1c1c1c',
|
||||
color: '#dbdbdb',
|
||||
colorStarted: '#8a8a8a',
|
||||
backgroundDeleted: '#0f0f0f',
|
||||
|
||||
Reference in New Issue
Block a user