Skip to content
Cirrus home
Sign in

Guide

Protect a position

Put a stop-loss and target on a position: held at your broker (GTT or stop order) where it can be, or watched by Cirrus.

A stop-loss limits a loss; a target books a profit. You can add them to a position you already hold, or to an order as you place it. Needs the triggers scope.

Where the protection lives: route #

Protection held by your broker keeps working even if nothing else does, so Cirrus uses it first. route says where it went:

routeHeld byWhen
auto (default)The best place availableBroker GTT or broker stop order when the case is simple, otherwise Cirrus.
gttYour broker, as a GTTDelivery and carry-forward positions, at brokers with GTTs, with a plain price stop-loss and/or target.
stop_orderYour broker, as a stop-loss orderIntraday (MIS) positions at brokers whose stop orders work reliably.
triggerCirrus serversAnything else: trailing stops, conditions, time limits. Checked on every tick; exits at market.

Ask for gtt or stop_order and the request is refused (422) when that route cannot take it. If the broker refuses, Cirrus protects the position at once instead (route: "trigger", the broker’s reason in route_reason).

Protect a position you hold #

Create a bracket trigger with the position’s entry price, a stop-loss and a target. This one is simple, so it goes to the broker as a GTT:

POST
curl -X POST "https://cirrus.pocketful.in/v2/triggers" \
  -H "Authorization: token $CIRRUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account": "PF1",
    "kind": "bracket",
    "legs": [
      {
        "instrument_token": "CT:TEST:RELIANCE",
        "side": "BUY",
        "quantity": 5,
        "product": "DELIVERY"
      }
    ],
    "spec": {
      "entry_px": 2500,
      "stop_loss": {
        "init_sl": "2475"
      },
      "target": {
        "when": "ltp >= 2550"
      }
    }
  }'
Response · 202
{
  "status": "success",
  "data": {
    "trigger_id": "7eb5eba9-7305-4548-b62b-b14773ee05dc",
    "command_id": "01M5VVFCDWXKW2HGN1Z6DFSYDT",
    "status": "accepted",
    "route": "gtt",
    "route_reason": "broker GTT holds the stop-loss, a server-side trigger the target (one-leg GTT broker)"
  },
  "error": null
}

Add a trailing stop and it can no longer live at the broker, so Cirrus holds it:

POST
curl -X POST "https://cirrus.pocketful.in/v2/triggers" \
  -H "Authorization: token $CIRRUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account": "P1",
    "kind": "bracket",
    "legs": [
      {
        "instrument_token": "CT:TEST:RELIANCE",
        "side": "BUY",
        "quantity": 5,
        "product": "MIS"
      }
    ],
    "spec": {
      "entry_px": 2500,
      "target": {
        "when": "ltp >= entry_px * 1.02"
      },
      "stop_loss": {
        "init_sl": "entry_px - 25",
        "trail": {
          "step": "5"
        }
      }
    }
  }'
Response · 202
{
  "status": "success",
  "data": {
    "trigger_id": "01M5VVFCDFRZFZ0A56Z1VHC8WJ",
    "command_id": "01M5VVFCDM23ZD6N7BKFGJ3KZD",
    "status": "accepted",
    "route": "trigger",
    "route_reason": "a trailing stop-loss is evaluated by the server (a GTT or broker stop cannot trail)"
  },
  "error": null
}

Protect an order as you place it #

Add protection to the order. The stop-loss and target are set up when it fills:

POST
curl -X POST "https://cirrus.pocketful.in/v1/orders" \
  -H "Authorization: token $CIRRUS_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "orders": [
      {
        "instrument_token": "CT:TEST:RELIANCE",
        "side": "BUY",
        "order_type": "LIMIT",
        "product": "MIS",
        "quantity": 5,
        "price": 2500,
        "accounts": [
          "P1"
        ],
        "protection": {
          "stop_loss": {
            "enabled": true,
            "type": "points",
            "value": 20
          },
          "target": {
            "enabled": true,
            "type": "points",
            "value": 40
          },
          "route": "trigger"
        }
      }
    ]
  }'
Response · 200
{
  "status": "success",
  "data": {
    "results": [
      {
        "order_index": 0,
        "account": "P1",
        "quantity": 5,
        "status": "accepted",
        "order_id": "PAPER-1",
        "message": null,
        "order_type": "LIMIT",
        "price": 2500,
        "protection": "trigger",
        "trigger_v2_id": "01M528W5RT4849ZV0QXFC6WPDD",
        "instrument_token": "CT:TEST:RELIANCE",
        "order_tag": "01M528W5RQR83SWDQVE74F02HZ"
      }
    ],
    "accepted": 1,
    "rejected": 0,
    "unknown": 0
  },
  "error": null
}

See what protects an order, and where, with GET /v1/orders/{order_id}/protection:

GET
curl "https://cirrus.pocketful.in/v1/orders/<order_id>/protection" \
  -H "Authorization: token $CIRRUS_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "account": "P1",
    "status": "armed",
    "route": "trigger",
    "rules": {
      "stop_loss": {
        "type": "points",
        "value": 20
      },
      "target": {
        "type": "points",
        "value": 40
      },
      "trail": null
    },
    "broker_id": null,
    "triggers": [
      {
        "trigger_id": "01JAC9X2K7QF0000000000TRG1",
        "version": "v2",
        "quantity": 5,
        "entry_price": 2499.5
      }
    ],
    "order_tag": "01JAC9X2K7QF0000000000PR01"
  },
  "error": null
}

Change or cancel it #

  • PATCH /v2/triggers/{trigger_id} moves the levels. At the broker it moves the GTT or stop order too.
  • DELETE /v2/triggers/{trigger_id} removes it (and cancels it at the broker).
  • POST /v2/triggers/{trigger_id}/pause and /resume stop and restart watching.

In the reference