Explore more topics
NexusTrade guide

Create an options trading strategy

Turn an options idea into complete entry, contract-selection, allocation and exit rules. Build an inactive NexusTrade draft and verify what was saved.

As of 2026-10-10

Jump to a section

TL;DR

Specify entry, contract selection, premium budget and both market and time exits before creating an options draft. The saved SPY long-call example enters above its 50-day average with no matching position, selects a 30 to 45 DTE call and uses a $1,000 premium budget. Its first simulated round trip earned $1.51 after commissions. Inspect selected quotes, quantities and closes separately from validation, and keep broad close rules away from unrelated matching positions.

See the first actual opening and close

Animation of the six checks NexusTrade's engine ran when the saved SPY long-call strategy's buy condition turned true on Jan 2, 2024: condition, expiration, strike, liquidity, size and fill, ending with 1 Feb 2 $472 call bought at $8.6544.
What happens after the strategy's condition turns true: the engine picks, sizes and prices the contract.
Show the table · 2 rows, 6 columns

Scroll sideways to compare all columns. Select a heading to sort.

2024-01-02 14:31:00SPY240202C00472000Buy to open1$8.6544$0.65
2024-01-19 14:31:00SPY240202C00472000Sell to close1$8.6825$0.65

A separate detailed run completed on 2026-10-10 with the same saved candidate, fixed dates and fees. It reproduced the lightweight result retained in the linked source record. The captured opening condition had SPY at $472.16, SMA50 at $461.57 and matching-position count 0. Both entry checks were true.

The first position opened on January 2 and closed on January 19, 2024, at 14 DTE. The time-exit close evaluation emitted 1 order. These are simulated Filled orders, not broker executions. The first position's P&L was $1.51 after recorded commissions, calculated from all its opening and closing premiums and quantities.

Compare the selected-candidate bid, ask and mid with the Filled-order premium. Follow the contract symbols and timestamps to connect selection, sizing and execution.

Start with the saved SPY long-call rules

Show the table · 7 rows, 2 columns
InputSaved example
UnderlyingSPY
EntryPrice > SMA(50, Day) AND matching OptionPositionCount = 0
Purchased callATM; nearest expiration 30 to 45 days away; ratio 1
Premium allocation$1,000 dollars; whole contracts must fit the resolved debit
CloseWhole matching position when price <= SMA50, or at 14 or fewer DTE
Order executionMarket; actual fills and fees are not shown by an authoring preview
Product readback3 saved rules; inactive paper example; zero positions; automated approval disabled

We built this long call in NexusTrade on October 10, 2026. The authoring preview returned valid with no issues. We saved the three rules in a chat draft, then saved the same rules in a dedicated inactive paper example for inspection in the native editor. Its readback confirmed paper, isActive:false, $10,000 simulated cash, zero positions and automated approval disabled. The captured trade walkthrough is near the top; the full backtest and rule details remain below.

The example uses SPY to demonstrate how an ETF option selector resolves. Starting simulated capital is $10,000. Each opening uses a $1,000 premium budget. The entry checks SPY price above its 50-day average and zero matching long-call positions. After a close, the rule may enter again when those conditions are true.

Calculate what this recorded trade earned

The displayed premiums changed from $8.6544 to $8.6825. For 1 contract with multiplier 100, ($8.6825 − $8.6544) × 100 − $0.65 − $0.65 = $1.51 after the two recorded commissions. This calculation uses the displayed rounded premiums. The contract closed before expiration, so an expiration-payoff formula would answer a different question.

Its opening checks were SPY above SMA50 and zero matching option positions. The complete source preserves those indicator values, selected contract, quote, fill and close. Compare the first trade with the full-year curve before attributing the whole return to this one position.

Write rules the builder can test

A strategy needs more than a name such as long call. Specify when to open, which contracts qualify, how much capital to use and when to close. The long call and bull call spread walkthroughs use SPY, a price above its 50-day average, a $1,000 premium budget and two exit rules. Other strategies declare their own signals and sizing. These choices define an educational test, not a recommendation.

Show the table · 5 rows, 3 columns

Scroll sideways to compare all columns. Select a heading to sort.

EntrySPY price > SMA(50, Day) and zero matching long callsAn existing matching position prevents another opening.
ContractsATM call; nearest expiry between 30 and 45 DTEActual symbol, strike and expiry chosen on each signal.
Allocation$1,000 dollars from $10,000 starting capitalWhole-contract quantity, debit, commissions and buying power.
Trend exitSPY price <= SMA(50, Day)Close all matching SPY spreads, not just one leg.
Time exit14 or fewer days to expirationA separate close rule with maxDte 14.

Build a reviewable draft with Aurora

Use the prepared request in the walkthrough above. Compare the returned saved rules with this guide’s exact entry, exit and sizing before planning a test.

Prompt
Create an undeployed research draft named SPY long call with $10,000 initial value. Underlying SPY. Open a custom long call only when Price(SPY) > SMA(SPY,50,Day) AND matching long call custom OptionPositionCount equals zero. Allocate $1,000 dollars. Buy an at-the-money (ATM) call, ratio 1, nearest expiration 30 to 45 days away. Close all matching SPY custom spreads when Price(SPY) <= SMA(SPY,50,Day). Add a separate close-all matching-spread rule with maxDte 14. Review the draft, correct any validation issues, save it and show its exact saved rules and identifier. Keep automated trading off. Stop after saving.

Check the same inputs in the native editor

For a paper portfolio, open Strategies, choose Open Options Position and the Long Call or Bull Call Spread preset. Set Underlying Asset, each leg's strike distance, Min DTE, Max DTE, expiration preference and Allocation. Add conditions and both Close Options Position rules separately. The preset supplies legs; it does not supply the whole strategy.

A chat draft and a native paper portfolio use different routes. In Portfolio, choose Drafts to inspect a chat draft or open it in Aurora. The native Strategies editor belongs to a paper or live portfolio. Keep the authoring example inactive and separate from other matching SPY positions, since close-all rules may close those too.

Compare your draft with tested examples

The strategy guides include exact authoring configurations, saved rule inputs and completed historical backtests. The long call and bull call spread also show the Python authoring example. Use those records to compare your own draft before submitting a test.

Plan a separate variant and later test

Review the optional next experiment

Keep one changed variant separate from the original. After the development comparison, freeze a chosen version before selecting a later period that has not influenced its rules.

  1. Create one variant, then test unseen dates

    Ask: "Change only the timed close trigger from 14 DTE to 10 DTE. Show the rule diff and compare both candidates on the 2024 development period with every other setting fixed." After choosing, freeze the rules and select another test period you have not inspected. The displayed 2024 results already make 2024 a viewed development period. Keep any later revisions in a new research cycle.

Create and backtest with Python

Use the Python SDK route

Python SDK 1.42.0. Save the runner below as run_long_call.py.

Install and download

Shell
python3 -m pip install nexustrade==1.42.0
export NEXUSTRADE_API_KEY="YOUR_API_KEY"
curl --fail --output long_call.py https://nexustrade.io/seo/strategy-examples/long-call.py

Create, test and inspect

Python
from long_call import create_long_call, backtest_long_call

book = create_long_call()
completed = backtest_long_call()
print(completed["result"])

Run

Shell
python3 run_long_call.py

Python strategy and backtest functions

View complete Python SDK functions

The backtest function submits the 2024 test with SPY as its benchmark, records events and waits for the result. Use a new request key when changing rules, dates or fees.

Python
import nexustrade as nt


def create_long_call():
    asset = nt.stock_asset("SPY")
    return nt.portfolio(
        "Public SEO example - Long call",
        [
            nt.strategy(
                "Open Long call",
                ((nt.Price(asset) > nt.SMA(asset, 50, "Day")) & (nt.OptionPositionCount("SPY", "call", "long", "custom") == nt.Value(0))),
                nt.open_option(
                    builder=nt.options_builder(
                        legs=[nt.leg(option_type="call", direction="long", min_days_to_expiration=30, max_days_to_expiration=45, preference="nearest", distance=0, ratio=1)],
                        underlying_symbol="SPY",
                        spread_type="custom"
                    ),
                    allocation={'type': 'dollars', 'amount': 1000}
                )
            ),
            nt.strategy(
                "Close when trend breaks",
                (nt.Price(asset) <= nt.SMA(asset, 50, "Day")),
                nt.close_option(
                    underlyings=['SPY'],
                    spread_type="custom",
                    close_scope="spread",
                    quantity={'type': 'all'}
                )
            ),
            nt.strategy(
                "Close at 14 DTE",
                (nt.Value(1) > nt.Value(0)),
                nt.close_option(
                    underlyings=['SPY'],
                    spread_type="custom",
                    close_scope="spread",
                    quantity={'type': 'all'},
                    triggers=[nt.dte_trigger(max_dte=14)]
                )
            ),
        ],
        initial_value=10000,
        alerts_enabled=False,
    )


def backtest_long_call(client=None):
    client = client or nt.NexusTradeClient.from_environment()
    operation = client.create_backtest(
        nt.backtest(
            create_long_call(),
            start_date="2024-01-01", end_date="2024-12-31",
            interval="Day", baseline_symbol="SPY",
            initial_value=10000, generate_events=True,
            dividend_policy="cash",
            fee_config={"Stock": {"type": "percent", "amount": 0.1},
                        "Cryptocurrency": {"type": "percent", "amount": 0.7},
                        "Option": {"type": "dollars", "amount": 0.65}},
        ),
        idempotency_key="explore-long-call-2024-spy-v1",
    )
    return client.wait_for_backtest(operation["id"])


# Build locally: book = create_long_call()
# Run and inspect: completed = backtest_long_call(); print(completed["result"])

Create and backtest with TypeScript

Use the TypeScript SDK route

TypeScript SDK 1.42.0. Save the runner below as run-long-call.ts.

Install and download

Shell
npm install nexustrade@1.42.0
npm install --save-dev tsx
export NEXUSTRADE_API_KEY="YOUR_API_KEY"
curl --fail --output long-call.ts https://nexustrade.io/seo/strategy-examples/long-call.ts

Create, test and inspect

TypeScript
import { createLongCall, backtestLongCall } from "./long-call";

async function main() {
  const book = createLongCall();
  const completed = await backtestLongCall();
  console.log(completed.result);
}

main().catch((error: unknown) => {
  console.error(error);
  process.exitCode = 1;
});

Run

Shell
npx tsx run-long-call.ts

TypeScript strategy and backtest functions

View complete TypeScript SDK functions

The same rules, dates and fees are used in both SDKs. The backtest function keeps its request key across retries.

TypeScript
import * as nt from "nexustrade";

export function createLongCall() {
  const asset = nt.stockAsset("SPY");
  return nt.portfolio(
    "Public SEO example - Long call",
    [
      nt.strategy(
          "Open Long call",
          nt.and(
              nt.gt(nt.Price(asset), nt.SMA(asset, 50, "Day")),
              nt.eq(nt.OptionPositionCount("SPY", "call", "long", "custom"), nt.Value(0))
          ),
          nt.openOption({ builder: nt.optionsBuilder({ legs: [nt.leg({ optionType: "call", direction: "long", minDaysToExpiration: 30, maxDaysToExpiration: 45, preference: "nearest", distance: 0, ratio: 1 })], underlyingSymbol: "SPY", spreadType: "custom" }), allocation: {"type": "dollars", "amount": 1000} })
      ),
      nt.strategy(
          "Close when trend breaks",
          nt.lte(nt.Price(asset), nt.SMA(asset, 50, "Day")),
          nt.closeOption({ underlyings: ["SPY"], spreadType: "custom", closeScope: "spread", quantity: {"type": "all"} })
      ),
      nt.strategy(
          "Close at 14 DTE",
          nt.gt(nt.Value(1), nt.Value(0)),
          nt.closeOption({ underlyings: ["SPY"], spreadType: "custom", closeScope: "spread", quantity: {"type": "all"}, triggers: [nt.dteTrigger({ maxDte: 14 })] })
      ),
    ],
    { initialValue: 10000, alertsEnabled: false }
  );
}

export async function backtestLongCall(client = new nt.NexusTradeClient()) {
  const operation = await client.createBacktest(
    nt.backtest(createLongCall(), {
      startDate: "2024-01-01", endDate: "2024-12-31",
      interval: "Day", baselineSymbol: "SPY",
      initialValue: 10000, generateEvents: true,
      dividendPolicy: "cash",
      feeConfig: {
        Stock: { type: "percent", amount: 0.1 },
        Cryptocurrency: { type: "percent", amount: 0.7 },
        Option: { type: "dollars", amount: 0.65 },
      },
    }),
    { idempotencyKey: "explore-long-call-2024-spy-v1" }
  );
  if (typeof operation.id !== "string") throw new Error("Missing backtest ID");
  return client.waitForBacktest(operation.id);
}

// Build locally: const book = createLongCall();
// Run and inspect: const completed = await backtestLongCall(); console.log(completed.result);

Next: run a fixed historical test

Continue exploring

Discussion

Sign in or create a free account to join the discussion.

No comments yet.

Aurora · AI research assistant

Try this in Aurora

Edit the request, then open it in Aurora. You choose when to send it.