πŸ”„ Iron Butterfly vs Iron Condor

Feature Iron Butterfly Iron Condor
Short Strikes Both at ATM (same strike) Different strikes (OTM)
Net Credit Higher Lower
Profit Zone Narrower Wider
Probability of Profit Lower Higher
Max Profit Likelihood Only at exact ATM price Between short strikes
Best For Low volatility, pinned price Range bound markets

Visual Comparison

Iron Condor

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” / \ / \ ──/───────────────────\── Short Put Short Call (OTM) (OTM)

Iron Butterfly

β”Œβ”€β” / β”‚ \ / β”‚ \ ──/──────┴──────\── Both Shorts at ATM

πŸ“ Files & Flows

Core Files

File Purpose API Environment
ib.json Entry flow β€” Opens new positions Paper
liquidation_flow.json Closes positions manually or scheduled Live
monitoring_flow.json Auto-monitors P&L, exits on thresholds Live
trade_history_flow.json Calculates historical P&L Live

Flow Descriptions

1. Entry Flow (ib.json)

Trigger: Monday 9:35 AM (cron) or Manual

1Calculate Friday expiry date
↓
2Fetch SPY price from Alpaca Data API
↓
3Calculate ATM strike (round to nearest $1)
↓
4Build OCC option symbols
↓
5Fetch options Greeks/prices
↓
6Calculate risk metrics & expected value
↓
7Submit 4-leg multi-leg order

2. Liquidation Flow (liquidation_flow.json)

Trigger: Thursday 2:40 PM (cron) or Manual

1Fetch all open positions
↓
2Filter SPY options
↓
3Group by expiry (handles multiple butterflies)
↓
4Build close orders with correct quantities
↓
5Submit multi-leg close orders
↓
6Calculate realized P&L and verify closure

3. Monitoring Flow (monitoring_flow.json)

Trigger: Every 5 minutes (repeating inject)

Exit Conditions:
  • Profit β‰₯ 50% of max β†’ Close
  • Profit β‰₯ 90% (near max) β†’ Close
  • Loss β‰₯ 80% β†’ Stop loss

4. Trade History (trade_history_flow.json)

Trigger: Manual

Fetches last 30 days of closed orders, matches entry/exit pairs by expiry, and calculates realized P&L, win rate, and cumulative statistics.

βš™οΈ Setup & Configuration

Prerequisites

  • Node-RED installed
  • Alpaca Account with options trading enabled
  • API Keys for both paper and live trading

Import Flows

  1. Open Node-RED
  2. Menu β†’ Import β†’ Clipboard
  3. Paste contents of each JSON file
  4. Deploy

Configuration (in ib.json)

// Set API Keys node
global.set("apiKeyP1", "YOUR_DATA_API_KEY");      // For market data
global.set("apiSecretP1", "YOUR_DATA_SECRET");
global.set("apiKeyP3", "YOUR_PAPER_TRADING_KEY"); // For paper trading
global.set("apiSecretP3", "YOUR_PAPER_SECRET");

// Strategy Configuration
global.set("underlying", "SPY");
global.set("quantity", 1);      // Number of contracts per leg
global.set("wingWidth", 10);    // Distance from ATM to long strikes

Live Trading Keys

For liquidation_flow.json, monitoring_flow.json, and trade_history_flow.json:

global.set("apiKeyLive", "YOUR_LIVE_API_KEY");
global.set("apiSecretLive", "YOUR_LIVE_SECRET");

πŸ”‘ API Keys

Key Types Used

Key Name Purpose Environment
apiKeyP1 / apiSecretP1 Market data (snapshots, Greeks) data.alpaca.markets
apiKeyP3 / apiSecretP3 Paper trading orders paper-api.alpaca.markets
apiKeyLive / apiSecretLive Live trading orders api.alpaca.markets

API Endpoints

Endpoint Purpose
/v2/stocks/SPY/snapshot Get SPY price
/v1beta1/options/snapshots Get options prices/Greeks
/v2/orders (paper) Submit paper orders
/v2/orders (live) Submit live orders
/v2/positions Get open positions

πŸ“¦ Order Structure

Alpaca Multi-Leg Order Format

{
  "order_class": "mleg",
  "type": "market",
  "time_in_force": "day",
  "qty": "5",
  "legs": [
    {
      "symbol": "SPY250117P00580000",
      "side": "buy",
      "ratio_qty": "1"
    },
    {
      "symbol": "SPY250117P00590000",
      "side": "sell",
      "ratio_qty": "1"
    },
    {
      "symbol": "SPY250117C00590000",
      "side": "sell",
      "ratio_qty": "1"
    },
    {
      "symbol": "SPY250117C00600000",
      "side": "buy",
      "ratio_qty": "1"
    }
  ]
}
⚠️ Important Notes:
  • qty at order level = number of spreads (actual contracts per leg)
  • ratio_qty at leg level = ratio between legs (always "1" for butterfly)
  • Both must be strings, not numbers
  • ratio_qty replaced the deprecated ratio field

OCC Symbol Format

SPY250117P00580000
β”‚   β”‚     β”‚ β”‚
β”‚   β”‚     β”‚ └── Strike Γ— 1000 (8 digits, padded with zeros)
β”‚   β”‚     └──── Option type (P=Put, C=Call)
β”‚   └────────── Expiry (YYMMDD)
└────────────── Underlying symbol

πŸšͺ Exit Management

Scheduled Exit

⏰ Thursday 2:40 PM EST

Why Thursday?

  • Avoids Friday gamma risk
  • Captures majority of theta decay
  • Provides buffer before expiration

Automated Monitoring Exits

Condition Threshold Rationale
Profit Target P&L β‰₯ 50% Secure profits before potential reversal
Max Profit P&L β‰₯ 90% Close when near max, avoid pin risk
Stop Loss P&L ≀ βˆ’80% Limit losses on breakout moves

Manual Exit

Click "Manual Liquidation Trigger" in the liquidation flow to close immediately.

πŸ’° P&L Calculation

Entry Metrics

// Net Credit = Premium received - Premium paid
netCreditReceived = shortCredit - longCost;

// Max Risk = Wing Width Γ— 100 - Net Credit
maxRisk = (wingWidth * 100 * quantity) - netCreditReceived;

Return Calculations

// Return on Capital (ROC)
returnOnCapital = (realizedPnL / maxRisk) * 100;

// Return on Credit
returnOnCredit = (realizedPnL / netCreditReceived) * 100;

// Annualized Return
annualizedReturn = (returnOnCapital / tradeDays) * 252;

P&L Summary Output

{
  "summary": {
    "completedTrades": 5,
    "totalPnL": "+$234.50",
    "winCount": 4,
    "lossCount": 1,
    "winRate": "80.0%",
    "avgPnLPerTrade": "+$46.90"
  }
}

Example Trade

πŸ“₯ Entry (Monday 9:35 AM)

SPY Price: $590.25
ATM Strike: $590
Wing Width: 10
Position:
- Buy  1x SPY 250117 P580 @ $0.80
- Sell 1x SPY 250117 P590 @ $2.50
- Sell 1x SPY 250117 C590 @ $2.50
- Buy  1x SPY 250117 C600 @ $0.80
Net Credit: $3.40
Max Profit: $340
Max Loss: $660

πŸ“€ Exit (Thursday 2:40 PM)

SPY Price: $589.50
Close Cost: ~$1.80
Realized P&L: 
  $3.40 - $1.80 = $1.60
  Γ— 100 = $160 profit
ROC: $160 / $660 = 24.2%

πŸ”§ Troubleshooting

Common Issues

❌ "No SPY options positions"

Cause: No open positions or wrong API keys

Fix: Verify live API keys are set and positions exist

❌ Order rejected β€” "Invalid ratio"

Cause: Using ratio instead of ratio_qty

Fix: Use "ratio_qty": "1" (string, not number)

❌ Order closes only 1 contract

Cause: Missing qty at order level

Fix: Include "qty": "N" at order level with actual quantity

⚠️ "API keys not configured"

Cause: Global variables not set

Fix: Run the "Initialize API Keys" inject node first

⚠️ Positions not closing completely

Cause: Multiple butterflies with different expiries

Fix: Flow groups by expiry and submits separate orders

Debug Tips

  • Enable debug nodes to see full payloads
  • Check Node-RED sidebar for warnings/errors
  • Use node.warn() output in function nodes
  • Verify API response codes (200/201 = success)

Logs to Check

  • Order submission: Look for order ID in response
  • Position fetch: Verify us_option asset class filter
  • Symbol format: Ensure no spaces/trimming issues

⚠️ Disclaimer

Options trading involves significant risk. This automation is provided as-is without warranty. Always monitor your positions and ensure you understand the risks involved. Past performance does not guarantee future results.

Ready to Automate Your Options Strategies?

Deploy Iron Butterfly and other strategies with MachineTrader's low-code platform.

Start Free Trial