# Setting a Stop Loss

Once a position is successfully opened via the solver’s **instant trading API**, it's worth setting a stop loss to protect that position. This ensures risk is bounded even if the bot goes offline or market conditions change unexpectedly.

***

### High-Level Flow

1. Authenticate with the Hedger API ([SIWE login](/exchange-builder-documentation/frontend-builder-technical-guidance/instant-trading/instant-login-eoa.md))
2. Open an instant market position
3. Let the **temporary quote ID** resolve into a permanent `quoteId`
4. Calculate the stop-loss price
5. Submit a stop-loss request to the solver API

> ⚠️ A stop loss **must reference a permanent `quoteId`**. You cannot attach SL/TP to a temporary quote.

***

### Authentication (SIWE Login)

Before any protected actions (open, stop loss, cancel, etc.), the bot must authenticate using **Sign-In With Ethereum (SIWE)**.

1. Fetch a nonce from the hedger
2. Build a SIWE message scoped to the **active trading account**
3. Sign the message with the owner wallet
4. Exchange the signature for a JWT access token

```python
token = login()
```

The returned `access_token` is used as a Bearer token for all subsequent requests.

***

### Opening the Position (Instant Open)

The bot opens a position using the solver’s `instant_open` endpoint.

Key points:

* Orders **must be market orders** (`orderType = 1`)
* The price is derived from the **Muon Oracle**
* Slippage is applied to guarantee execution
* Collateral parameters are calculated using `get_locked_params`

```python
temp_quote_id, open_price = open_instant_trade(token)
```

#### Returned Values

* `temp_quote_id`: Temporary identifier for the order
* `open_price`: The raw Muon price used to derive SL/TP levels

***

### Resolving the Temporary Quote ID

Instant trades initially return a **temporary quote ID**.\
Before setting a stop loss, the bot must wait until this temp ID is finalized into a **permanent `quoteId`**.

This is done by polling the user’s active quotes:

```python
quote_id = poll_quote_status(token, temp_quote_id)
```

#### Why This Is Required

* Stop loss and take profit requests are validated against finalized on-chain quotes
* Using a temp ID will result in rejection

***

### Calculating the Stop Loss Price

Once the quote is confirmed, derives a stop-loss price relative to the entry price.

In this example:

* The bot is **LONG**
* Stop loss is set at **80% of entry price**

```python
sl_price = (open_price * Decimal('0.8')).quantize(
    Decimal("0.000001"),
    rounding=ROUND_DOWN
)
```

#### Notes

* Precision should match the symbol’s supported decimals
* For SHORT positions, this logic would be inverted

***

### Stop Loss Request Payload

The stop loss is submitted using the `stop_loss` endpoint.

{% hint style="info" %}
This refers to [PerpsHub TPSL Implementation](/api-endpoints-and-deployments/solver-addresses-and-endpoints/perps-hub/perpshub-tp-sl-implementation.md), check [Rasa's TPSL Implementation](/api-endpoints-and-deployments/solver-addresses-and-endpoints/rasa-capital/rasa-solver-tp-sl-implementation.md) for detailed instructions on how to construct their payload.
{% endhint %}

#### Payload Structure

```json
{
  "userAddress": "<wallet address>",
  "accountAddress": "<active account>",
  "positionSide": 0,
  "symbolId": 4,
  "requestedPrice": "ENTRY_PRICE",
  "quoteId": 12345,
  "tpPrice": "",
  "slPrice": "STOP_LOSS_PRICE",
  "timestamp": 1710000000000
}
```

#### Field Explanation

| Field            | Description                          |
| ---------------- | ------------------------------------ |
| `userAddress`    | Wallet that signed the login message |
| `accountAddress` | Trading account (EOA or sub-account) |
| `positionSide`   | `0 = Long`, `1 = Short`              |
| `symbolId`       | Internal symbol identifier           |
| `requestedPrice` | Original entry price                 |
| `quoteId`        | Permanent quote ID                   |
| `tpPrice`        | Leave empty if not setting TP        |
| `slPrice`        | Calculated stop loss price           |
| `timestamp`      | Client-side timestamp (ms)           |

***

### Sending the Stop Loss Request

```python
response = requests.post(
    f"{HEDGER_URL}/stop_loss",
    json=payload,
    headers={
        "Content-Type": "application/json",
        "Authorization": f"Bearer {token}"
    }
)
```

On success, the solver will acknowledge the stop loss and register it for on-chain execution when the trigger price is reached.

***

### Complete Execution Flow

```
Login (SIWE)
   ↓
Instant Open Position
   ↓
Receive temp_quote_id
   ↓
Poll until quoteId is finalized
   ↓
Compute stop loss price
   ↓
POST /stop_loss
```

A full example implementation can be found in our SYMM SDK.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.symm.io/trader-documentation/building-a-trading-bot/setting-a-stop-loss.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
