Skip to content

Feat/panoptic straddle strategy - #84

Open
Rythys wants to merge 4 commits into
Logarithm-Labs:devfrom
Rythys:feat/panoptic-straddle-strategy
Open

Feat/panoptic straddle strategy#84
Rythys wants to merge 4 commits into
Logarithm-Labs:devfrom
Rythys:feat/panoptic-straddle-strategy

Conversation

@Rythys

@Rythys Rythys commented May 15, 2026

Copy link
Copy Markdown

What

Adds PanopticStraddleStrategy — a long-straddle strategy on the Panoptic
perpetual options protocol over Uniswap V3 ETH/USDC 0.3% pool.

Why

Panoptic buyers are the natural counterpart to passive LPs (who are implicitly
short gamma). This strategy enters when pool implied volatility is cheap and
exits on a directional move.

Test plan

  • L1 unit tests: tests/core/test_panoptic_straddle.py (53 tests)
  • L2 e2e synthetic: tests/core/e2e/test_e2e_panoptic_straddle_synthetic.py (10 tests)
  • All 63 tests pass: pytest -m core
  • pre-commit run --all-files clean
  • L5 real-data (requires TheGraph API key, run manually)

@Rythys
Rythys requested a review from 0xBoringWozniak as a code owner May 15, 2026 19:08
@0xBoringWozniak 0xBoringWozniak self-assigned this May 18, 2026
@0xBoringWozniak 0xBoringWozniak added the area: strategy fractal/strategies/ — BasisTrading, HyperliquidBasis, TauReset. label May 18, 2026
@0xBoringWozniak
0xBoringWozniak requested a review from Copilot May 18, 2026 16:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new core strategy module implementing a Panoptic-based long straddle with a Uniswap V3 LP baseline, plus accompanying unit/e2e tests and documentation updates.

Changes:

  • Introduce PanopticStraddleStrategy / PanopticStraddleEntity and supporting state/params in fractal/strategies/panoptic_straddle.py.
  • Add L1 unit tests and L2 synthetic e2e tests for the new strategy.
  • Expose the strategy from fractal.strategies, and update README badge + CHANGELOG entry.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
fractal/strategies/panoptic_straddle.py Adds the new Panoptic straddle entity + strategy implementation.
fractal/strategies/__init__.py Re-exports new strategy/entity/state/params via package init and __all__.
tests/core/test_panoptic_straddle.py Adds unit/invariant tests for the straddle entity/strategy (currently inlines copies).
tests/core/e2e/test_e2e_panoptic_straddle_synthetic.py Adds deterministic synthetic e2e coverage for strategy branches/metrics.
README.md Updates DOI badge formatting/source.
CHANGELOG.md Adds an Unreleased entry documenting the new strategy.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/core/test_panoptic_straddle.py Outdated
Comment on lines +21 to +37
# ---------------------------------------------------------------------------
# Inline copies of the strategy classes.
# In the real PR these live in fractal/strategies/panoptic_straddle.py and
# are imported from there. They are inlined here so the test file is
# self-contained and can be reviewed independently of the strategy PR.
# ---------------------------------------------------------------------------

from collections import deque
from dataclasses import dataclass
from datetime import UTC, datetime
from typing import Deque, List

import numpy as np

from fractal.core.base import Action, ActionToTake, BaseStrategy, BaseStrategyParams


Comment thread tests/core/test_panoptic_straddle.py Outdated

import numpy as np

from fractal.core.base import Action, ActionToTake, BaseStrategy, BaseStrategyParams
Comment on lines +369 to +385
for i, price in enumerate(prices):
iv = iv_values[i] if iv_values is not None else 0.60
ts = datetime(2023, 1, 1, i % 24, tzinfo=UTC)
result.append(Observation(
timestamp=ts,
states={
"STRADDLE": PanopticPoolGlobalState(
price=price, fees=fees, liquidity=liquidity,
volume=5e8, tvl=5e8, iv_annual=iv,
),
"LP": UniswapV3LPGlobalState(
price=price, fees=fees, liquidity=liquidity,
volume=5e8, tvl=5e8,
),
},
))
return result
Comment on lines +38 to +53
for i, price in enumerate(prices):
iv = iv_values[i] if iv_values is not None else 0.60
result.append(Observation(
timestamp=datetime(2023, 1, 1, i % 24, tzinfo=UTC),
states={
"STRADDLE": PanopticPoolGlobalState(
price=price, fees=fees, liquidity=liquidity,
volume=5e8, tvl=5e8, iv_annual=iv,
),
"LP": UniswapV3LPGlobalState(
price=price, fees=fees, liquidity=liquidity,
volume=5e8, tvl=5e8,
),
},
))
return result
Comment thread fractal/strategies/panoptic_straddle.py Outdated
Comment on lines +285 to +294
if (total_costs > 0
and straddle.intrinsic_value
>= self._params.TAKE_PROFIT_MULT * total_costs):
reason = 'TAKE_PROFIT'
elif total_costs >= (self._params.INITIAL_BALANCE
* self._params.STOP_LOSS_BUDGET_PCT):
reason = 'STOP_LOSS'
elif s.bars_held >= self._params.MAX_HOLD_BARS:
reason = 'TIME_STOP'
else:
Comment on lines +122 to +131
@property
def intrinsic_value(self) -> float:
if not self._internal_state.is_open:
return 0.0
return abs(self._global_state.price - self._internal_state.entry_price)

@property
def balance(self) -> float:
pnl = self.intrinsic_value - self._internal_state.accumulated_premium
return self._internal_state.cash + self._internal_state.collateral + pnl
Comment thread fractal/strategies/panoptic_straddle.py Outdated
Comment on lines +269 to +274
if straddle.internal_state.cash < notional * self._params.COLLATERAL_PCT:
return []
return [ActionToTake('STRADDLE', Action('open', {
'notional': notional,
'collateral': notional * self._params.COLLATERAL_PCT,
'commission': notional * self._params.PANOPTIC_COMMISSION_PCT,
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: strategy fractal/strategies/ — BasisTrading, HyperliquidBasis, TauReset.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants