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:
| route | Held by | When |
|---|---|---|
auto (default) | The best place available | Broker GTT or broker stop order when the case is simple, otherwise Cirrus. |
gtt | Your broker, as a GTT | Delivery and carry-forward positions, at brokers with GTTs, with a plain price stop-loss and/or target. |
stop_order | Your broker, as a stop-loss order | Intraday (MIS) positions at brokers whose stop orders work reliably. |
trigger | Cirrus servers | Anything 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:
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"
}
}
}'import os
import requests
response = requests.post(
"https://cirrus.pocketful.in/v2/triggers",
headers={
"Authorization": f"token {os.environ['CIRRUS_API_KEY']}",
},
json={
"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",
},
},
},
timeout=10,
)
print(response.status_code, response.json())const response = await fetch('https://cirrus.pocketful.in/v2/triggers', {
method: 'POST',
headers: {
Authorization: `token ${process.env.CIRRUS_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"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"
}
}
}),
});
const body = await response.json();
console.log(response.status, body);{
"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:
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"
}
}
}
}'import os
import requests
response = requests.post(
"https://cirrus.pocketful.in/v2/triggers",
headers={
"Authorization": f"token {os.environ['CIRRUS_API_KEY']}",
},
json={
"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",
},
},
},
},
timeout=10,
)
print(response.status_code, response.json())const response = await fetch('https://cirrus.pocketful.in/v2/triggers', {
method: 'POST',
headers: {
Authorization: `token ${process.env.CIRRUS_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"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"
}
}
}
}),
});
const body = await response.json();
console.log(response.status, body);{
"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:
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"
}
}
]
}'import os
import uuid
import requests
response = requests.post(
"https://cirrus.pocketful.in/v1/orders",
headers={
"Authorization": f"token {os.environ['CIRRUS_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"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",
},
},
],
},
timeout=10,
)
print(response.status_code, response.json())const response = await fetch('https://cirrus.pocketful.in/v1/orders', {
method: 'POST',
headers: {
Authorization: `token ${process.env.CIRRUS_API_KEY}`,
'Idempotency-Key': crypto.randomUUID(),
'Content-Type': 'application/json',
},
body: JSON.stringify({
"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"
}
}
]
}),
});
const body = await response.json();
console.log(response.status, body);{
"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:
curl "https://cirrus.pocketful.in/v1/orders/<order_id>/protection" \
-H "Authorization: token $CIRRUS_API_KEY"import os
import requests
response = requests.get(
"https://cirrus.pocketful.in/v1/orders/<order_id>/protection",
headers={
"Authorization": f"token {os.environ['CIRRUS_API_KEY']}",
},
timeout=10,
)
print(response.status_code, response.json())const response = await fetch('https://cirrus.pocketful.in/v1/orders/<order_id>/protection', {
method: 'GET',
headers: {
Authorization: `token ${process.env.CIRRUS_API_KEY}`,
},
});
const body = await response.json();
console.log(response.status, body);{
"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}/pauseand/resumestop and restart watching.
In the reference
- Triggers Alerts, stop-loss, targets, entries, ladders and loss limits the server watches tick by tick.
- GTT orders Good-till-triggered orders the broker holds for you.
- Bracket and cover orders Orders the broker protects with its own stop-loss and target.
- Protection (classic triggers) The first trigger API: protect one position with a stop-loss, target and trail.