1294 lines
32 KiB
YAML
1294 lines
32 KiB
YAML
openapi: 3.1.0
|
|||
|
|
info:
|
||
|
|
title: Invest Copilot API
|
||
|
|
description: AI-native investment research and portfolio copilot
|
||
|
|
version: 0.1.0
|
||
|
|
contact:
|
||
|
|
name: Invest Copilot Team
|
||
|
|
email: dev@invest-copilot.local
|
||
|
|
|
||
|
|
servers:
|
||
|
|
- url: http://localhost:3000/api/v1
|
||
|
|
description: Development server
|
||
|
|
- url: https://api.invest-copilot.local/api/v1
|
||
|
|
description: Production server
|
||
|
|
|
||
|
|
tags:
|
||
|
|
- name: stocks
|
||
|
|
description: Stock search, profiles, and data
|
||
|
|
- name: watchlists
|
||
|
|
description: Watchlist management
|
||
|
|
- name: strategies
|
||
|
|
description: Strategy creation and management
|
||
|
|
- name: screeners
|
||
|
|
description: Stock screeners
|
||
|
|
- name: sectors
|
||
|
|
description: Sector rotation analysis
|
||
|
|
- name: alerts
|
||
|
|
description: Real-time alerts and notifications
|
||
|
|
- name: streaming
|
||
|
|
description: Server-Sent Events for real-time updates
|
||
|
|
|
||
|
|
paths:
|
||
|
|
# ─── Stock Search & Profile ──────────────────────────────
|
||
|
|
|
||
|
|
/search:
|
||
|
|
get:
|
||
|
|
tags: [stocks]
|
||
|
|
summary: Search stocks by ticker or name
|
||
|
|
operationId: searchStocks
|
||
|
|
parameters:
|
||
|
|
- name: q
|
||
|
|
in: query
|
||
|
|
required: true
|
||
|
|
description: Search query (ticker or company name)
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
minLength: 1
|
||
|
|
maxLength: 50
|
||
|
|
- name: limit
|
||
|
|
in: query
|
||
|
|
schema:
|
||
|
|
type: integer
|
||
|
|
minimum: 1
|
||
|
|
maximum: 50
|
||
|
|
default: 10
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: Search results
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/SearchResult'
|
||
|
|
400:
|
||
|
|
description: Invalid search query
|
||
|
|
|
||
|
|
/stocks/{ticker}:
|
||
|
|
get:
|
||
|
|
tags: [stocks]
|
||
|
|
summary: Get full stock profile with all data
|
||
|
|
operationId: getStockProfile
|
||
|
|
parameters:
|
||
|
|
- name: ticker
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
example: AAPL
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: Complete stock profile
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/StockProfileResponse'
|
||
|
|
404:
|
||
|
|
description: Stock not found
|
||
|
|
|
||
|
|
/stocks/{ticker}/peers:
|
||
|
|
get:
|
||
|
|
tags: [stocks]
|
||
|
|
summary: Get peer group with relative performance
|
||
|
|
operationId: getStockPeers
|
||
|
|
parameters:
|
||
|
|
- name: ticker
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
example: AAPL
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: Peer group data
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/PeerGroupResponse'
|
||
|
|
|
||
|
|
/stocks/{ticker}/price/history:
|
||
|
|
get:
|
||
|
|
tags: [stocks]
|
||
|
|
summary: Get historical price data
|
||
|
|
operationId: getPriceHistory
|
||
|
|
parameters:
|
||
|
|
- name: ticker
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
example: AAPL
|
||
|
|
- name: interval
|
||
|
|
in: query
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
enum: [1m, 5m, 15m, 30m, 1h, 1d, 1w, 1M]
|
||
|
|
default: 1d
|
||
|
|
- name: start
|
||
|
|
in: query
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
example: "2024-01-01T00:00:00Z"
|
||
|
|
- name: end
|
||
|
|
in: query
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
example: "2024-12-31T23:59:59Z"
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: Price history
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/PriceEvent'
|
||
|
|
|
||
|
|
/stocks/{ticker}/sec-filings:
|
||
|
|
get:
|
||
|
|
tags: [stocks]
|
||
|
|
summary: Get SEC filings with analysis
|
||
|
|
operationId: getSecFilings
|
||
|
|
parameters:
|
||
|
|
- name: ticker
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
example: AAPL
|
||
|
|
- name: form_type
|
||
|
|
in: query
|
||
|
|
description: Filter by form type
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
enum: [10-K, 10-Q, 8-K, 4, 13F, 13D, 13G]
|
||
|
|
- name: limit
|
||
|
|
in: query
|
||
|
|
schema:
|
||
|
|
type: integer
|
||
|
|
minimum: 1
|
||
|
|
maximum: 100
|
||
|
|
default: 20
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: SEC filings
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/SecFiling'
|
||
|
|
|
||
|
|
/stocks/{ticker}/insider-trades:
|
||
|
|
get:
|
||
|
|
tags: [stocks]
|
||
|
|
summary: Get insider trading activity
|
||
|
|
operationId: getInsiderTrades
|
||
|
|
parameters:
|
||
|
|
- name: ticker
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
example: AAPL
|
||
|
|
- name: limit
|
||
|
|
in: query
|
||
|
|
schema:
|
||
|
|
type: integer
|
||
|
|
minimum: 1
|
||
|
|
maximum: 100
|
||
|
|
default: 20
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: Insider trades
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/InsiderTrade'
|
||
|
|
|
||
|
|
/stocks/{ticker}/sentiment:
|
||
|
|
get:
|
||
|
|
tags: [stocks]
|
||
|
|
summary: Get sentiment signals from all sources
|
||
|
|
operationId: getStockSentiment
|
||
|
|
parameters:
|
||
|
|
- name: ticker
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
example: AAPL
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: Sentiment signals
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/SentimentResponse'
|
||
|
|
|
||
|
|
# ─── Watchlists ─────────────────────────────────────────
|
||
|
|
|
||
|
|
/watchlists:
|
||
|
|
get:
|
||
|
|
tags: [watchlists]
|
||
|
|
summary: Get all user watchlists
|
||
|
|
operationId: getUserWatchlists
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: List of watchlists
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/Watchlist'
|
||
|
|
post:
|
||
|
|
tags: [watchlists]
|
||
|
|
summary: Create a new watchlist
|
||
|
|
operationId: createWatchlist
|
||
|
|
requestBody:
|
||
|
|
required: true
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: object
|
||
|
|
required: [name]
|
||
|
|
properties:
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
minLength: 1
|
||
|
|
maxLength: 255
|
||
|
|
description:
|
||
|
|
type: string
|
||
|
|
maxLength: 1000
|
||
|
|
responses:
|
||
|
|
201:
|
||
|
|
description: Watchlist created
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/Watchlist'
|
||
|
|
|
||
|
|
/watchlists/{id}:
|
||
|
|
get:
|
||
|
|
tags: [watchlists]
|
||
|
|
summary: Get watchlist with items and live prices
|
||
|
|
operationId: getWatchlist
|
||
|
|
parameters:
|
||
|
|
- name: id
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: Watchlist with items
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/WatchlistWithPrices'
|
||
|
|
put:
|
||
|
|
tags: [watchlists]
|
||
|
|
summary: Update watchlist
|
||
|
|
operationId: updateWatchlist
|
||
|
|
parameters:
|
||
|
|
- name: id
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
requestBody:
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
description:
|
||
|
|
type: string
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: Watchlist updated
|
||
|
|
delete:
|
||
|
|
tags: [watchlists]
|
||
|
|
summary: Delete watchlist
|
||
|
|
operationId: deleteWatchlist
|
||
|
|
parameters:
|
||
|
|
- name: id
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
responses:
|
||
|
|
204:
|
||
|
|
description: Watchlist deleted
|
||
|
|
|
||
|
|
/watchlists/{id}/items:
|
||
|
|
get:
|
||
|
|
tags: [watchlists]
|
||
|
|
summary: Get watchlist items
|
||
|
|
operationId: getWatchlistItems
|
||
|
|
parameters:
|
||
|
|
- name: id
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: Watchlist items
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/WatchlistItem'
|
||
|
|
post:
|
||
|
|
tags: [watchlists]
|
||
|
|
summary: Add ticker to watchlist
|
||
|
|
operationId: addWatchlistItem
|
||
|
|
parameters:
|
||
|
|
- name: id
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
requestBody:
|
||
|
|
required: true
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: object
|
||
|
|
required: [ticker]
|
||
|
|
properties:
|
||
|
|
ticker:
|
||
|
|
type: string
|
||
|
|
maxLength: 20
|
||
|
|
type:
|
||
|
|
type: string
|
||
|
|
enum: [stock, etf, index]
|
||
|
|
notes:
|
||
|
|
type: string
|
||
|
|
maxLength: 500
|
||
|
|
responses:
|
||
|
|
201:
|
||
|
|
description: Item added
|
||
|
|
delete:
|
||
|
|
tags: [watchlists]
|
||
|
|
summary: Remove ticker from watchlist
|
||
|
|
operationId: removeWatchlistItem
|
||
|
|
parameters:
|
||
|
|
- name: id
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
- name: ticker
|
||
|
|
in: query
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
responses:
|
||
|
|
204:
|
||
|
|
description: Item removed
|
||
|
|
|
||
|
|
# ─── Strategies ─────────────────────────────────────────
|
||
|
|
|
||
|
|
/strategies:
|
||
|
|
get:
|
||
|
|
tags: [strategies]
|
||
|
|
summary: Get all user strategies
|
||
|
|
operationId: getUserStrategies
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: List of strategies
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/Strategy'
|
||
|
|
post:
|
||
|
|
tags: [strategies]
|
||
|
|
summary: Create a new strategy
|
||
|
|
operationId: createStrategy
|
||
|
|
requestBody:
|
||
|
|
required: true
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: object
|
||
|
|
required: [name, type, conditions]
|
||
|
|
properties:
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
minLength: 1
|
||
|
|
maxLength: 255
|
||
|
|
description:
|
||
|
|
type: string
|
||
|
|
maxLength: 1000
|
||
|
|
type:
|
||
|
|
type: string
|
||
|
|
enum: [technical, fundamental, hybrid]
|
||
|
|
conditions:
|
||
|
|
type: object
|
||
|
|
required: [rules, logic]
|
||
|
|
properties:
|
||
|
|
rules:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
type: object
|
||
|
|
required: [indicator, operator, value]
|
||
|
|
properties:
|
||
|
|
indicator:
|
||
|
|
type: string
|
||
|
|
operator:
|
||
|
|
type: string
|
||
|
|
enum: [lt, gt, lte, gte, eq, neq, crossover, crossbelow]
|
||
|
|
value:
|
||
|
|
type: number
|
||
|
|
period:
|
||
|
|
type: integer
|
||
|
|
source:
|
||
|
|
type: string
|
||
|
|
description:
|
||
|
|
type: string
|
||
|
|
logic:
|
||
|
|
type: string
|
||
|
|
enum: [AND, OR]
|
||
|
|
timeframe:
|
||
|
|
type: string
|
||
|
|
responses:
|
||
|
|
201:
|
||
|
|
description: Strategy created
|
||
|
|
|
||
|
|
/strategies/{id}:
|
||
|
|
get:
|
||
|
|
tags: [strategies]
|
||
|
|
summary: Get strategy details
|
||
|
|
operationId: getStrategy
|
||
|
|
parameters:
|
||
|
|
- name: id
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: Strategy details
|
||
|
|
put:
|
||
|
|
tags: [strategies]
|
||
|
|
summary: Update strategy
|
||
|
|
operationId: updateStrategy
|
||
|
|
parameters:
|
||
|
|
- name: id
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
requestBody:
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
description:
|
||
|
|
type: string
|
||
|
|
conditions:
|
||
|
|
type: object
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: Strategy updated
|
||
|
|
delete:
|
||
|
|
tags: [strategies]
|
||
|
|
summary: Delete strategy
|
||
|
|
operationId: deleteStrategy
|
||
|
|
parameters:
|
||
|
|
- name: id
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
responses:
|
||
|
|
204:
|
||
|
|
description: Strategy deleted
|
||
|
|
|
||
|
|
/strategies/{id}/backtest:
|
||
|
|
post:
|
||
|
|
tags: [strategies]
|
||
|
|
summary: Run backtest on a strategy
|
||
|
|
operationId: backtestStrategy
|
||
|
|
parameters:
|
||
|
|
- name: id
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
requestBody:
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
start_date:
|
||
|
|
type: string
|
||
|
|
format: date
|
||
|
|
end_date:
|
||
|
|
type: string
|
||
|
|
format: date
|
||
|
|
watchlist_id:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: Backtest results
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/BacktestResult'
|
||
|
|
|
||
|
|
# ─── Screeners ──────────────────────────────────────────
|
||
|
|
|
||
|
|
/screeners:
|
||
|
|
get:
|
||
|
|
tags: [screeners]
|
||
|
|
summary: Get user screeners
|
||
|
|
operationId: getUserScreeners
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: List of screeners
|
||
|
|
post:
|
||
|
|
tags: [screeners]
|
||
|
|
summary: Create a new screener
|
||
|
|
operationId: createScreener
|
||
|
|
requestBody:
|
||
|
|
required: true
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: object
|
||
|
|
required: [name, conditions]
|
||
|
|
properties:
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
description:
|
||
|
|
type: string
|
||
|
|
conditions:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
type: object
|
||
|
|
required: [field, operator, value]
|
||
|
|
properties:
|
||
|
|
field:
|
||
|
|
type: string
|
||
|
|
operator:
|
||
|
|
type: string
|
||
|
|
enum: [lt, gt, lte, gte, eq, neq]
|
||
|
|
value:
|
||
|
|
type: number
|
||
|
|
responses:
|
||
|
|
201:
|
||
|
|
description: Screener created
|
||
|
|
|
||
|
|
/screeners/{id}/run:
|
||
|
|
post:
|
||
|
|
tags: [screeners]
|
||
|
|
summary: Execute a screener
|
||
|
|
operationId: runScreener
|
||
|
|
parameters:
|
||
|
|
- name: id
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: Screener results
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
results:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/ScreenerResult'
|
||
|
|
total:
|
||
|
|
type: integer
|
||
|
|
runAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
|
||
|
|
/screeners/{id}/results:
|
||
|
|
get:
|
||
|
|
tags: [screeners]
|
||
|
|
summary: Get last screener results
|
||
|
|
operationId: getScreenerResults
|
||
|
|
parameters:
|
||
|
|
- name: id
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: Screener results
|
||
|
|
|
||
|
|
# ─── Sector Rotation ────────────────────────────────────
|
||
|
|
|
||
|
|
/sectors/rotation:
|
||
|
|
get:
|
||
|
|
tags: [sectors]
|
||
|
|
summary: Get current sector rotation analysis
|
||
|
|
operationId: getSectorRotation
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: Current rotation analysis
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/SectorRotationResponse'
|
||
|
|
post:
|
||
|
|
tags: [sectors]
|
||
|
|
summary: Trigger manual rotation scan
|
||
|
|
operationId: triggerRotationScan
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: Scan completed
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
$ref: '#/components/schemas/SectorRotationResponse'
|
||
|
|
|
||
|
|
/sectors/rotation/history:
|
||
|
|
get:
|
||
|
|
tags: [sectors]
|
||
|
|
summary: Get historical rotation data
|
||
|
|
operationId: getRotationHistory
|
||
|
|
parameters:
|
||
|
|
- name: from
|
||
|
|
in: query
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
format: date
|
||
|
|
- name: to
|
||
|
|
in: query
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
format: date
|
||
|
|
- name: sector
|
||
|
|
in: query
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
example: XLK
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: Historical rotations
|
||
|
|
|
||
|
|
# ─── Alerts ─────────────────────────────────────────────
|
||
|
|
|
||
|
|
/alerts:
|
||
|
|
get:
|
||
|
|
tags: [alerts]
|
||
|
|
summary: Get user alerts
|
||
|
|
operationId: getUserAlerts
|
||
|
|
parameters:
|
||
|
|
- name: status
|
||
|
|
in: query
|
||
|
|
description: Filter by status
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
enum: [active, resolved, dismissed]
|
||
|
|
default: active
|
||
|
|
- name: limit
|
||
|
|
in: query
|
||
|
|
schema:
|
||
|
|
type: integer
|
||
|
|
default: 50
|
||
|
|
maximum: 200
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: List of alerts
|
||
|
|
content:
|
||
|
|
application/json:
|
||
|
|
schema:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/Alert'
|
||
|
|
delete:
|
||
|
|
tags: [alerts]
|
||
|
|
summary: Clear resolved alerts
|
||
|
|
operationId: clearResolvedAlerts
|
||
|
|
responses:
|
||
|
|
204:
|
||
|
|
description: Alerts cleared
|
||
|
|
|
||
|
|
/alerts/{id}/resolve:
|
||
|
|
post:
|
||
|
|
tags: [alerts]
|
||
|
|
summary: Mark alert as resolved
|
||
|
|
operationId: resolveAlert
|
||
|
|
parameters:
|
||
|
|
- name: id
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: Alert resolved
|
||
|
|
|
||
|
|
/alerts/{id}/dismiss:
|
||
|
|
post:
|
||
|
|
tags: [alerts]
|
||
|
|
summary: Dismiss an alert
|
||
|
|
operationId: dismissAlert
|
||
|
|
parameters:
|
||
|
|
- name: id
|
||
|
|
in: path
|
||
|
|
required: true
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: Alert dismissed
|
||
|
|
|
||
|
|
# ─── Streaming (SSE) ───────────────────────────────────
|
||
|
|
|
||
|
|
/stream/alerts:
|
||
|
|
get:
|
||
|
|
tags: [streaming]
|
||
|
|
summary: Server-Sent Events stream for real-time alerts
|
||
|
|
operationId: getAlertStream
|
||
|
|
responses:
|
||
|
|
200:
|
||
|
|
description: SSE stream
|
||
|
|
content:
|
||
|
|
text/event-stream:
|
||
|
|
schema:
|
||
|
|
type: string
|
||
|
|
example: |
|
||
|
|
event: alert
|
||
|
|
data: {"id":"abc","message":"RSI oversold on AAPL","ticker":"AAPL"}
|
||
|
|
|
||
|
|
event: rotation
|
||
|
|
data: {"sector":"XLK","signal":"in","rankChange":3}
|
||
|
|
|
||
|
|
components:
|
||
|
|
schemas:
|
||
|
|
# ─── Stock Data ───────────────────────────────────────
|
||
|
|
|
||
|
|
SearchResult:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
ticker:
|
||
|
|
type: string
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
exchange:
|
||
|
|
type: string
|
||
|
|
sector:
|
||
|
|
type: string
|
||
|
|
marketCap:
|
||
|
|
type: number
|
||
|
|
|
||
|
|
PriceEvent:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
date:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
open:
|
||
|
|
type: number
|
||
|
|
high:
|
||
|
|
type: number
|
||
|
|
low:
|
||
|
|
type: number
|
||
|
|
close:
|
||
|
|
type: number
|
||
|
|
volume:
|
||
|
|
type: integer
|
||
|
|
adjustedClose:
|
||
|
|
type: number
|
||
|
|
|
||
|
|
StockProfileResponse:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
profile:
|
||
|
|
$ref: '#/components/schemas/StockProfile'
|
||
|
|
price:
|
||
|
|
$ref: '#/components/schemas/PriceEvent'
|
||
|
|
peers:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/Peer'
|
||
|
|
sentiment:
|
||
|
|
$ref: '#/components/schemas/SentimentResponse'
|
||
|
|
secFilings:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/SecFiling'
|
||
|
|
insiderTrades:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/InsiderTrade'
|
||
|
|
|
||
|
|
StockProfile:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
ticker:
|
||
|
|
type: string
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
exchange:
|
||
|
|
type: string
|
||
|
|
sector:
|
||
|
|
type: string
|
||
|
|
industry:
|
||
|
|
type: string
|
||
|
|
marketCap:
|
||
|
|
type: number
|
||
|
|
description:
|
||
|
|
type: string
|
||
|
|
website:
|
||
|
|
type: string
|
||
|
|
nullable: true
|
||
|
|
ceo:
|
||
|
|
type: string
|
||
|
|
nullable: true
|
||
|
|
employees:
|
||
|
|
type: integer
|
||
|
|
nullable: true
|
||
|
|
peRatio:
|
||
|
|
type: number
|
||
|
|
nullable: true
|
||
|
|
eps:
|
||
|
|
type: number
|
||
|
|
nullable: true
|
||
|
|
dividendYield:
|
||
|
|
type: number
|
||
|
|
nullable: true
|
||
|
|
beta:
|
||
|
|
type: number
|
||
|
|
nullable: true
|
||
|
|
|
||
|
|
Peer:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
ticker:
|
||
|
|
type: string
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
similarityScore:
|
||
|
|
type: number
|
||
|
|
relativeStrength:
|
||
|
|
type: number
|
||
|
|
priceChange1d:
|
||
|
|
type: number
|
||
|
|
priceChange5d:
|
||
|
|
type: number
|
||
|
|
priceChange30d:
|
||
|
|
type: number
|
||
|
|
|
||
|
|
PeerGroupResponse:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
ticker:
|
||
|
|
type: string
|
||
|
|
peers:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/Peer'
|
||
|
|
benchmark:
|
||
|
|
type: string
|
||
|
|
benchmarkChange1d:
|
||
|
|
type: number
|
||
|
|
|
||
|
|
SecFiling:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
ticker:
|
||
|
|
type: string
|
||
|
|
cik:
|
||
|
|
type: string
|
||
|
|
formType:
|
||
|
|
type: string
|
||
|
|
filingDate:
|
||
|
|
type: string
|
||
|
|
format: date
|
||
|
|
reportDate:
|
||
|
|
type: string
|
||
|
|
format: date
|
||
|
|
accessionNumber:
|
||
|
|
type: string
|
||
|
|
url:
|
||
|
|
type: string
|
||
|
|
contentSummary:
|
||
|
|
type: string
|
||
|
|
sentimentScore:
|
||
|
|
type: number
|
||
|
|
tags:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
type: string
|
||
|
|
|
||
|
|
InsiderTrade:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
ticker:
|
||
|
|
type: string
|
||
|
|
insiderName:
|
||
|
|
type: string
|
||
|
|
insiderTitle:
|
||
|
|
type: string
|
||
|
|
transactionDate:
|
||
|
|
type: string
|
||
|
|
format: date
|
||
|
|
transactionType:
|
||
|
|
type: string
|
||
|
|
enum: [BUY, SELL, GIFT, IN_EX]
|
||
|
|
shares:
|
||
|
|
type: integer
|
||
|
|
pricePerShare:
|
||
|
|
type: number
|
||
|
|
totalValue:
|
||
|
|
type: number
|
||
|
|
sharesOwnedAfter:
|
||
|
|
type: integer
|
||
|
|
filingDate:
|
||
|
|
type: string
|
||
|
|
format: date
|
||
|
|
|
||
|
|
SentimentResponse:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
ticker:
|
||
|
|
type: string
|
||
|
|
signals:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/SentimentSignal'
|
||
|
|
averageScore:
|
||
|
|
type: number
|
||
|
|
confidence:
|
||
|
|
type: number
|
||
|
|
|
||
|
|
SentimentSignal:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
source:
|
||
|
|
type: string
|
||
|
|
score:
|
||
|
|
type: number
|
||
|
|
minimum: -1
|
||
|
|
maximum: 1
|
||
|
|
confidence:
|
||
|
|
type: number
|
||
|
|
timestamp:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
context:
|
||
|
|
type: string
|
||
|
|
|
||
|
|
# ─── Watchlists ───────────────────────────────────────
|
||
|
|
|
||
|
|
Watchlist:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
id:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
description:
|
||
|
|
type: string
|
||
|
|
nullable: true
|
||
|
|
isDefault:
|
||
|
|
type: boolean
|
||
|
|
itemCount:
|
||
|
|
type: integer
|
||
|
|
createdAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
updatedAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
|
||
|
|
WatchlistWithPrices:
|
||
|
|
allOf:
|
||
|
|
- $ref: '#/components/schemas/Watchlist'
|
||
|
|
- type: object
|
||
|
|
properties:
|
||
|
|
items:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/WatchlistItemWithPrice'
|
||
|
|
|
||
|
|
WatchlistItem:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
ticker:
|
||
|
|
type: string
|
||
|
|
type:
|
||
|
|
type: string
|
||
|
|
enum: [stock, etf, index]
|
||
|
|
notes:
|
||
|
|
type: string
|
||
|
|
nullable: true
|
||
|
|
addedAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
priceAtAddition:
|
||
|
|
type: number
|
||
|
|
nullable: true
|
||
|
|
|
||
|
|
WatchlistItemWithPrice:
|
||
|
|
allOf:
|
||
|
|
- $ref: '#/components/schemas/WatchlistItem'
|
||
|
|
- type: object
|
||
|
|
properties:
|
||
|
|
currentPrice:
|
||
|
|
type: number
|
||
|
|
priceChange1d:
|
||
|
|
type: number
|
||
|
|
priceChangePercent:
|
||
|
|
type: number
|
||
|
|
marketCap:
|
||
|
|
type: number
|
||
|
|
nullable: true
|
||
|
|
|
||
|
|
# ─── Strategies ───────────────────────────────────────
|
||
|
|
|
||
|
|
Strategy:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
id:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
description:
|
||
|
|
type: string
|
||
|
|
type:
|
||
|
|
type: string
|
||
|
|
enum: [technical, fundamental, hybrid]
|
||
|
|
conditions:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
rules:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
indicator:
|
||
|
|
type: string
|
||
|
|
operator:
|
||
|
|
type: string
|
||
|
|
value:
|
||
|
|
type: number
|
||
|
|
period:
|
||
|
|
type: integer
|
||
|
|
source:
|
||
|
|
type: string
|
||
|
|
description:
|
||
|
|
type: string
|
||
|
|
logic:
|
||
|
|
type: string
|
||
|
|
enum: [AND, OR]
|
||
|
|
timeframe:
|
||
|
|
type: string
|
||
|
|
backtestResults:
|
||
|
|
$ref: '#/components/schemas/BacktestResult'
|
||
|
|
nullable: true
|
||
|
|
createdAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
updatedAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
|
||
|
|
BacktestResult:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
startDate:
|
||
|
|
type: string
|
||
|
|
format: date
|
||
|
|
endDate:
|
||
|
|
type: string
|
||
|
|
format: date
|
||
|
|
totalReturn:
|
||
|
|
type: number
|
||
|
|
annualizedReturn:
|
||
|
|
type: number
|
||
|
|
maxDrawdown:
|
||
|
|
type: number
|
||
|
|
sharpeRatio:
|
||
|
|
type: number
|
||
|
|
winRate:
|
||
|
|
type: number
|
||
|
|
totalTrades:
|
||
|
|
type: integer
|
||
|
|
avgHoldTime:
|
||
|
|
type: string
|
||
|
|
equityCurve:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
type: number
|
||
|
|
|
||
|
|
# ─── Screeners ────────────────────────────────────────
|
||
|
|
|
||
|
|
Screener:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
id:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
name:
|
||
|
|
type: string
|
||
|
|
description:
|
||
|
|
type: string
|
||
|
|
nullable: true
|
||
|
|
lastRunAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
nullable: true
|
||
|
|
resultsCount:
|
||
|
|
type: integer
|
||
|
|
createdAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
updatedAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
|
||
|
|
ScreenerResult:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
ticker:
|
||
|
|
type: string
|
||
|
|
matchScore:
|
||
|
|
type: number
|
||
|
|
rankedPosition:
|
||
|
|
type: integer
|
||
|
|
resultData:
|
||
|
|
type: object
|
||
|
|
|
||
|
|
# ─── Sector Rotation ──────────────────────────────────
|
||
|
|
|
||
|
|
SectorRotation:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
detectionDate:
|
||
|
|
type: string
|
||
|
|
format: date
|
||
|
|
sectorTicker:
|
||
|
|
type: string
|
||
|
|
sectorName:
|
||
|
|
type: string
|
||
|
|
rankNow:
|
||
|
|
type: integer
|
||
|
|
rankPrevious:
|
||
|
|
type: integer
|
||
|
|
rankChange:
|
||
|
|
type: integer
|
||
|
|
momentum20d:
|
||
|
|
type: number
|
||
|
|
momentum50d:
|
||
|
|
type: number
|
||
|
|
momentum200d:
|
||
|
|
type: number
|
||
|
|
relativeStrength:
|
||
|
|
type: number
|
||
|
|
signal:
|
||
|
|
type: string
|
||
|
|
enum: [in, out, stable, accelerating]
|
||
|
|
analysisSummary:
|
||
|
|
type: string
|
||
|
|
|
||
|
|
SectorRotationResponse:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
date:
|
||
|
|
type: string
|
||
|
|
format: date
|
||
|
|
rotations:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
$ref: '#/components/schemas/SectorRotation'
|
||
|
|
inRotation:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
type: string
|
||
|
|
outOfRotation:
|
||
|
|
type: array
|
||
|
|
items:
|
||
|
|
type: string
|
||
|
|
macroContext:
|
||
|
|
type: object
|
||
|
|
nullable: true
|
||
|
|
|
||
|
|
# ─── Alerts ───────────────────────────────────────────
|
||
|
|
|
||
|
|
Alert:
|
||
|
|
type: object
|
||
|
|
properties:
|
||
|
|
id:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
watchlistId:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
strategyId:
|
||
|
|
type: string
|
||
|
|
format: uuid
|
||
|
|
nullable: true
|
||
|
|
ticker:
|
||
|
|
type: string
|
||
|
|
type:
|
||
|
|
type: string
|
||
|
|
enum: [strategy_trigger, sec_filing, sentiment, rotation, price]
|
||
|
|
triggerType:
|
||
|
|
type: string
|
||
|
|
message:
|
||
|
|
type: string
|
||
|
|
severity:
|
||
|
|
type: string
|
||
|
|
enum: [info, warning, critical]
|
||
|
|
status:
|
||
|
|
type: string
|
||
|
|
enum: [active, resolved, dismissed]
|
||
|
|
triggeredAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
resolvedAt:
|
||
|
|
type: string
|
||
|
|
format: date-time
|
||
|
|
nullable: true
|
||
|
|
metadata:
|
||
|
|
type: object
|