# Signals

## Latest Bar Construction

At `00:01` every hour we kick off our data ingestion pipeline, which draws from a dozen data sources in order to write the latest bar to our market data warehouse.  This process takes about 4 minutes, after which we run inference on the latest bar and generate the next signal.

We recommend starting to long poll the `/signals` endpoint at `00:01` every 10s for the latest signal.  Long poll until you receive an object where `is_live_signal = true` .

## Request Signals

```python
curl -X GET "https://api.nautilus.finance/api/v1/signals?&asset=Bitcoin&num_signals=1" \
 -H "x-api-key: <your-api-key>"
```

**Note:** you must whitelist your IP address to access the API

### Delays

There are occasional delays in our data ingestion pipeline due to upstream exchange/vendor issues.  As a result some signals may arrive closer to `00:15` or even `00:30` in rare cases.  Continue to long poll until the live signal arrives.  This occurs in less than 5% of signals based on analysis of data ingestion metrics.

## Data Model

Below is a sample JSON returned by the signals endpoint:

{% code title="Flipping from short to long" %}

```json
{
  "prediction_datetime": "2025-07-08 20:00",  # UTC
  "pred_price": 108694.2699,
  "close": 108630.54,  # close price of bar
  "action": "flip",  # ["flip", "add", "trim", "neutral"]
  "position": "long",  # ["long", "short", "neutral"]
  "num_trade_blocks": 1,
  "position_trade_blocks": 20,
  "max_position_trade_blocks": 30,
  "position_saturation": 0.67,  # [0, 1]
  "leverage": 4,  # optional leverage multiplier [1, 5]
  "stop_loss": 0.04,  # (4%) unleveraged price move
  "take_profit": 0.10,  # (10%) unleveraged price move
  "is_live_signal": true  # if (server time - prediction_datetime) < 2 hours
}
```

{% endcode %}

You should realize position through `direction` and `position_saturation`&#x20;

**NOTE: If our API goes down due to an upstream vendor/provider issue and you do not receive a new signal for 3 hours then go flat.**

## Keep in Mind

* `position_saturation` is `position_trade_blocks` / `max_position_trade_blocks`&#x20;
* `action` is one of `add` to current position, `flip` direction, or `neutral` (stay in position but do not add)
* All datetimes are UTC
