Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/najmulhossainnj/Hedge-fund-backend/llms.txt

Use this file to discover all available pages before exploring further.

The Signals API powers the transition from raw ML model predictions to actionable trading decisions. A SignalLogic record stores a rule tree — a recursive JSON structure of conditions and combinators produced by the visual Signal Builder UI. At generation time, the platform fetches OHLCV market data, runs the feature pipeline, invokes the model, and passes the resulting prediction DataFrame through the rule tree to emit per-bar BUY, SELL, or HOLD labels. Alternatively, a registered plugin key can replace the rule tree for fully custom signal generation logic. Both synchronous and Celery-backed asynchronous generation are supported.

SignalLogic CRUD

Create Signal Logic

POST /api/v1/signals Persists a new rule tree definition linked to an optional strategy. The rule_tree field must be a non-empty list of RuleGroup objects as produced by the Signal Builder UI. On success the record is immediately available for use in signal generation.
curl -X POST https://api.example.com/api/v1/signals \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Momentum Long/Short Rules",
    "description": "Buy on high prediction + positive sentiment; sell on low prediction",
    "rule_tree": [
      {
        "action": "BUY",
        "combinator": "AND",
        "rules": [
          {"field": "prediction", "operator": ">", "value": 0.65},
          {"field": "sentiment",  "operator": ">", "value": 0.4}
        ]
      },
      {
        "action": "SELL",
        "combinator": "AND",
        "rules": [
          {"field": "prediction", "operator": "<", "value": 0.35},
          {"field": "sentiment",  "operator": "<", "value": -0.2}
        ]
      }
    ],
    "output_mode": "discrete",
    "position_mode": "long_short",
    "strategy_id": "d4e5f6a7-b8c9-0123-def0-234567890123"
  }'

Request Body (SignalLogicCreate)

name
string
required
Human-readable name for the signal logic. Maximum 255 characters. Indexed for fast lookup.
description
string
Optional description explaining the signal hypothesis. Maximum 1000 characters.
rule_tree
RuleGroup[]
required
Ordered list of RuleGroup objects. The rule engine evaluates groups top-to-bottom and returns the action of the first matching group. Each group contains an action, a combinator, and a list of rules (leaf conditions or nested branch nodes).See the Rule Tree Structure section for the full schema.
output_mode
string
default:"\"discrete\""
Controls how the rule engine emits signals.
  • "discrete" — emits string labels "BUY", "SELL", or "HOLD".
  • "numeric" — emits +1, -1, or 0 respectively.
position_mode
string
default:"\"long_short\""
Intended position-taking behaviour. Informational metadata consumed by the portfolio layer.
  • "long_only" — only BUY signals are acted on.
  • "long_short" — both BUY and SELL signals are acted on.
  • "portfolio" — signal weight is managed at portfolio construction level.
strategy_id
uuid
Optional UUID of the parent Strategy. When provided, this signal logic is scoped to that strategy and can be filtered by strategy_id on the list endpoint.

Response — 201 Created

id
uuid
Unique identifier of the created signal logic record.
name
string
Signal logic name.
description
string | null
Optional description.
rule_tree
RuleGroup[]
The stored rule tree exactly as submitted.
output_mode
string
"discrete" or "numeric".
position_mode
string
"long_only", "long_short", or "portfolio".
strategy_id
uuid | null
Linked strategy UUID, if provided.
version
integer
Optimistic-concurrency version counter. Starts at 1.
created_at
datetime
ISO 8601 creation timestamp.
updated_at
datetime
ISO 8601 last-update timestamp.

List Signal Logic

GET /api/v1/signals Returns a paginated list of signal logic records. Optionally filter by strategy_id to retrieve only the rules associated with a particular strategy.
# All signal logic, first page
curl "https://api.example.com/api/v1/signals?skip=0&limit=50"

# Filtered by strategy
curl "https://api.example.com/api/v1/signals?strategy_id=d4e5f6a7-b8c9-0123-def0-234567890123"

Query Parameters

strategy_id
uuid
When provided, returns only signal logic records linked to this strategy UUID. When omitted, all records are returned subject to skip/limit.
skip
integer
default:"0"
Number of records to skip for offset-based pagination.
limit
integer
default:"100"
Maximum records to return per page.

Response — 200 OK

Returns list[SignalLogicRead]. Each element has the same shape as the Create Signal Logic response.

Get Signal Logic

GET /api/v1/signals/{signal_id} Retrieves a single signal logic record by its UUID.
curl https://api.example.com/api/v1/signals/e5f6a7b8-c9d0-1234-ef01-345678901234

Path Parameters

signal_id
uuid
required
UUID of the signal logic record to retrieve.

Response

200 OK with SignalLogicRead. Returns 404 Not Found with {"detail": "SignalLogic not found"} when no record exists for the given ID.

Update Signal Logic

PATCH /api/v1/signals/{signal_id} Partially updates a signal logic record. Only the fields present in the request body are modified.
curl -X PATCH https://api.example.com/api/v1/signals/e5f6a7b8-c9d0-1234-ef01-345678901234 \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Tightened prediction threshold to 0.70",
    "rule_tree": [
      {
        "action": "BUY",
        "combinator": "AND",
        "rules": [
          {"field": "prediction", "operator": ">", "value": 0.70},
          {"field": "sentiment",  "operator": ">", "value": 0.4}
        ]
      }
    ]
  }'

Path Parameters

signal_id
uuid
required
UUID of the signal logic record to update.

Request Body (SignalLogicUpdate — all fields optional)

name
string
Updated name.
description
string | null
Updated description.
rule_tree
RuleGroup[]
Full replacement rule tree. The entire tree is replaced — partial updates within the tree are not supported.
output_mode
string
"discrete" or "numeric".
position_mode
string
"long_only", "long_short", or "portfolio".
strategy_id
uuid | null
Re-link or unlink the parent strategy.

Response — 200 OK

Returns the updated SignalLogicRead object. Returns 404 Not Found if the record does not exist.

Delete Signal Logic

DELETE /api/v1/signals/{signal_id} Permanently removes a signal logic record.
curl -X DELETE https://api.example.com/api/v1/signals/e5f6a7b8-c9d0-1234-ef01-345678901234

Path Parameters

signal_id
uuid
required
UUID of the signal logic record to delete.

Response

204 No Content on success. 404 Not Found if the record does not exist.
Deleting a signal logic record that is currently referenced by a strategy’s signal_logic_id will leave a dangling reference on the strategy. Update or clear the strategy’s signal_logic_id before deleting the record.

Rule Tree Validation

Validate Rule Tree

POST /api/v1/signals/validate-rule-tree Dry-runs a rule tree against a synthetic single-row DataFrame to catch field name typos, unsupported operators, and structural errors before wiring the rule tree to a live model. No database writes occur. This endpoint is intended for use by the Signal Builder UI to provide instant feedback during rule authoring.
curl -X POST https://api.example.com/api/v1/signals/validate-rule-tree \
  -H "Content-Type: application/json" \
  -d '{
    "rule_tree": [
      {
        "action": "BUY",
        "combinator": "AND",
        "rules": [
          {"field": "prediction", "operator": ">", "value": 0.65},
          {"field": "sentiment",  "operator": ">", "value": 0.4}
        ]
      },
      {
        "action": "SELL",
        "combinator": "OR",
        "rules": [
          {"field": "prediction", "operator": "<", "value": 0.35},
          {"field": "rsi_14",     "operator": ">", "value": 70}
        ]
      }
    ],
    "sample_fields": ["prediction", "sentiment", "rsi_14"]
  }'

Request Body

rule_tree
RuleGroup[]
required
The rule tree to validate. Must be a non-empty list. Returns 422 Unprocessable Entity if empty.
sample_fields
string[]
default:"[\"prediction\"]"
List of field names that will be present in the real feature DataFrame at generation time. The validator builds a synthetic row with 0.0 for each field and exercises every branch. If a rule references a field not in sample_fields, validation will report a KeyError.

Response — 200 OK

valid
boolean
true when the rule tree evaluated against the synthetic sample without any errors.
errors
string[]
List of error messages encountered during evaluation. Empty when valid is true. Contains KeyError messages for unknown fields and ValueError messages for unsupported operator/value combinations.
rule_group_count
integer
Number of top-level rule groups in the submitted tree. Useful for confirming the parser read the structure correctly.
Always pass the complete set of feature column names your strategy uses as sample_fields. The validator treats each as a float column initialised to 0.0, which exercises threshold comparisons at the boundary between signal regions.

Rule Tree Structure

The rule engine supports a recursive tree of leaf conditions and branch combinators inside each top-level RuleGroup.

RuleGroup (top-level)

Each entry in the rule_tree array is a RuleGroup. The engine evaluates groups in declaration order and returns the action of the first group whose conditions are all satisfied. If no group matches, the bar receives a HOLD signal.
action
string
required
Signal to emit when this group matches. One of "BUY", "SELL", "HOLD".
combinator
string
required
How to combine the child rules. "AND" requires all rules to pass; "OR" requires at least one.
rules
LeafRule[] | BranchRule[]
required
Ordered list of conditions. Each element is either a leaf condition or a nested branch node.

LeafRule (leaf condition)

field
string
required
Column name in the feature DataFrame (e.g. "prediction", "rsi_14", "sentiment").
operator
string
required
Comparison operator. One of ">", "<", ">=", "<=", "==", "!=".
value
float | string
required
Right-hand side of the comparison. Numeric for most feature fields; string for categorical columns.

BranchRule (nested combinator)

combinator
string
required
"AND" or "OR" — applied to the child rules list.
rules
LeafRule[] | BranchRule[]
required
Recursively nested conditions.

Signal Generation

Generate Signals (Synchronous)

POST /api/v1/signals/generate Runs the full signal generation pipeline end-to-end and returns the results synchronously. The pipeline:
  1. Loads the specified MLModel and Feature records from the database.
  2. Fetches OHLCV market data for the symbol/timeframe/date range via the market data client.
  3. Runs the FeaturePipeline to compute and join all feature columns.
  4. Invokes the model to produce a prediction series.
  5. Evaluates the rule tree (or plugin) against the predictions to produce per-bar signals.
  6. Returns a statistical summary and a 20-row preview.
You must supply either signal_logic_id or plugin_key — not both, and not neither. Violating this constraint returns 422 Unprocessable Entity.
curl -X POST https://api.example.com/api/v1/signals/generate \
  -H "Content-Type: application/json" \
  -d '{
    "model_id":        "c3d4e5f6-a7b8-9012-cdef-123456789012",
    "feature_ids": [
      "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "b2c3d4e5-f6a7-8901-bcde-f12345678901"
    ],
    "signal_logic_id": "e5f6a7b8-c9d0-1234-ef01-345678901234",
    "symbol":          "AAPL",
    "timeframe":       "1d",
    "start_date":      "2024-01-01T00:00:00Z",
    "end_date":        "2024-10-31T00:00:00Z",
    "target_horizon":  1
  }'

Request Body (SignalGenerateRequest)

model_id
uuid
required
UUID of the trained MLModel to use for generating predictions.
feature_ids
uuid[]
required
List of Feature UUIDs whose computed columns will form the model input DataFrame. All IDs must exist; a single missing ID returns 404.
signal_logic_id
uuid
UUID of the SignalLogic record whose rule tree converts predictions to signals. Mutually exclusive with plugin_key.
plugin_key
string
Key of a registered signal generator plugin to use instead of a rule tree. Retrieve available keys from GET /api/v1/signals/plugins/available. Mutually exclusive with signal_logic_id.
plugin_params
object
default:"{}"
Key-value parameters forwarded to the plugin at generation time. Ignored when signal_logic_id is used.
symbol
string
required
Ticker symbol to generate signals for (e.g. "AAPL", "BTC-USD").
timeframe
string
default:"\"1d\""
Candle resolution. Must match the timeframe the features were designed for.
start_date
datetime
required
ISO 8601 start of the generation window (inclusive).
end_date
datetime
required
ISO 8601 end of the generation window (inclusive).
target_horizon
integer
default:"1"
Forward-looking prediction horizon in bars. Passed to the Celery task for async generation; informational for synchronous calls.

Response — 200 OK (SignalGenerateResponse)

signal_logic_id
uuid | null
The signal_logic_id echoed from the request. null when a plugin was used.
plugin_key
string | null
The plugin_key echoed from the request. null when a rule tree was used.
model_id
uuid
UUID of the model that generated the predictions.
symbol
string
Ticker symbol echoed from the request.
metadata
object
Pipeline metadata returned by the signal engine (e.g. model version, feature pipeline hashes).
summary
object
Aggregate signal statistics over the full date range.
preview
object[]
First 20 rows of the joined prediction + signal DataFrame. Each record contains at minimum a timestamp, the model prediction value, and the resulting signal label.

Generate Signals (Asynchronous)

POST /api/v1/signals/generate/async Dispatches signal generation as a Celery background task and immediately returns a task_id. Use the task ID to poll your Celery result backend for completion status. This endpoint accepts exactly the same request body as the synchronous POST /api/v1/signals/generate.
curl -X POST https://api.example.com/api/v1/signals/generate/async \
  -H "Content-Type: application/json" \
  -d '{
    "model_id":        "c3d4e5f6-a7b8-9012-cdef-123456789012",
    "feature_ids":     ["a1b2c3d4-e5f6-7890-abcd-ef1234567890"],
    "signal_logic_id": "e5f6a7b8-c9d0-1234-ef01-345678901234",
    "symbol":          "NVDA",
    "timeframe":       "1d",
    "start_date":      "2020-01-01T00:00:00Z",
    "end_date":        "2024-10-31T00:00:00Z"
  }'

Request Body

Identical to SignalGenerateRequest — see the synchronous endpoint for full parameter documentation.

Response — 200 OK

task_id
string
Celery task ID. Poll your result backend (e.g. Redis) or a task-status endpoint to check completion.
status
string
Always "PENDING" immediately after dispatch.
Use the async endpoint for large date ranges or high-frequency timeframes (e.g. 1m over multiple years) where the synchronous pipeline would exceed request timeout limits.

List Signal Plugins

GET /api/v1/signals/plugins/available Returns the keys of all registered signal generator plugins. Plugin keys can be passed as the plugin_key parameter in signal generation requests as an alternative to a persisted rule tree.
curl https://api.example.com/api/v1/signals/plugins/available

Response — 200 OK

plugins
string[]
Array of plugin key strings registered in the signal_registry. Each key uniquely identifies a plugin class that implements the signal generation interface.

Error Reference

StatusCondition
404 Not FoundSignalLogic, MLModel, or one or more Feature IDs do not exist.
422 Unprocessable Entityrule_tree is empty on validate; both or neither of signal_logic_id/plugin_key provided on generate; no OHLCV data returned for the requested range.
204 No ContentSuccessful deletion — no response body.

Build docs developers (and LLMs) love