nexusquant-sdk
NexusQuant strategy provider Python SDK.
Installation
pip install nexusquant-sdk
Requires Python 3.10 or newer.
Quick start
import nexusquant_sdk as nq
# Authenticate once (opens browser)
nq.auth_login()
# List your strategies
strategies = nq.strategy_list()
# Send a signal
nq.strategy_send_signal_single(
"my_alpha",
ticker="AAPL",
direction="buy",
price=150.0,
quantity=100,
order_type="LIMIT",
)
Authentication
Login uses the OAuth 2.0 PKCE flow against Cognito. Tokens are stored locally at
the path returned by nq.auth_credentials_path(), so you only log in once.
nq.auth_login() # opens Cognito Hosted UI, saves tokens
nq.auth_logged_in() # True if a token is present
nq.auth_refresh() # force-refresh the ID token via refresh token
nq.auth_logout() # delete local tokens
nq.auth_credentials_path() # path to the credentials file
Override defaults with environment variables:
| Variable | Default |
|---|---|
NEXUSQUANT_API_ENDPOINT |
https://api.nexusquant.co |
NEXUSQUANT_COGNITO_DOMAIN |
auth.lookatwallstreet.com |
NEXUSQUANT_COGNITO_CLIENT_ID |
(built-in) |
NEXUSQUANT_REDIRECT_URI |
http://127.0.0.1:8251/callback |
Strategy API
# Register / update a strategy
nq.strategy_register("my_alpha", "My Alpha Strategy", output_unit="SHARE_COUNT")
# List strategies
nq.strategy_list()
# Signal history
nq.strategy_signal_history("my_alpha", limit=20)
# Send a single signal
nq.strategy_send_signal_single(
"my_alpha",
ticker="AAPL",
direction="buy", # "buy" or "sell"
price=150.0,
quantity=100, # share count
order_type="LIMIT" # "MARKET" or "LIMIT"
)
# Send a multi-route signals map
nq.strategy_send_signals("my_alpha", {"default": {...}})
# ...or the same map from a JSON file
nq.strategy_send_signals_from_path("my_alpha", "signals.json")
# Subscriber configuration snapshot
nq.strategy_subscriber_config("my_alpha")
SizingPolicy
A SizingPolicy replaces the fixed quantity on a signal with a formula that
decides the order quantity — and optionally a limit price — at order time. You
publish the formula once; each signal then carries only the parameter values it
needs. Anything that depends on the individual subscriber's account is never sent
by you: it is bound inside that user's own container the moment the order is placed.
What a policy is made of
Two things, and nothing else:
expr— the formulas, keyed by output slot.params— the names you promise to supply with every signal. Just the names.
nq.policy_publish(
"my_alpha",
ticker="TQQQ",
expr={
"f_depth": "exp(-k_depth * depth / 10)",
"buy.quantity": "target_shares * f_depth * clamp(1 - pos_ratio, 0, 1)",
"buy.price": "ref_price * (1 - slip)",
"sell.quantity": "held_shares * exit_frac",
},
params=["target_shares", "k_depth", "depth", "ref_price", "slip", "exit_frac"],
)
Intermediate names (f_depth above) are fine — only the slot names below are read
as output — but an expr must define at least one output slot, and an
intermediate name may not contain a dot. ticker is passed separately because it
is not part of the artifact: the same formula pointed at another symbol is the same
formula.
Output slots
nq.OUTPUT_SLOTS is the full set:
| Slot | What the formula yields |
|---|---|
buy.quantity / sell.quantity |
Share count (floored) |
buy.price / sell.price |
Limit price — supplied ⇒ limit order, omitted ⇒ market order |
The container picks the slot matching the signal's direction. A formula with only
buy slots does not block a sell signal — it simply has no opinion on that
direction, and the quantity you sent with the signal is used instead.
Account state is not yours to send
nq.ACCOUNT_FEATURES holds the per-user names — pos_ratio, held_shares,
account_value, cash_available, buying_power, pos_pct_of_account,
position_value, allocation_usd, pending_sell_shares. Your formula may
reference them, but you must never supply a value for one: those values do not
leave the execution plane. Sending one is rejected, whether or not your formula
uses it.
nq.policy_features() is the authority on which names exist at all, and on which
account-state names the container can currently supply (suppliable) — a name
that exists but cannot be supplied will pass your editor and fail at publish. Call
it before writing a formula:
nq.policy_features() # {features, shared, account, functions, output_slots, guidance}
The SDK carries fallback copies of the account-name set and the whitelisted DSL functions for when the registry cannot be reached, but those go stale as the server registry grows — when the fallback is used, local success does not imply the server will accept.
Publishing, listing, stopping
# Publishing IS the go-live action. There is no shadow or canary step, and the
# previous version on the same slot is deactivated.
nq.policy_publish("my_alpha", ticker="TQQQ", expr={...}, params=[...], profile="normal")
# Everything published for one strategy: full artifact, slots, params, account names used
nq.policy_list("my_alpha", ticker="TQQQ", mode="active")
# Emergency stop for a live version — not a promotion step, since publish already went live
nq.policy_set_mode("TQQQ/normal/…/abc123", "off") # "active" to restore
policy_publish(..., check_names=False) skips fetching the registry before
validating locally. Leave it on: forgetting to list a name in params is the most
common mistake, and catching it locally beats being rejected after the fact.
Sending a signal against a policy
nq.policy_send_signal(
"my_alpha",
ticker="TQQQ",
price=51.2,
direction="buy",
params={
"target_shares": 10, "k_depth": 0.5, "depth": 3,
"ref_price": 51.2, "slip": 0.002, "exit_frac": 0.25,
},
)
By default this fetches the active policy first and uses it to validate and coerce your parameters. Three checks, each mirroring the server:
| Situation | Result | Why not something else |
|---|---|---|
| A declared parameter is missing | Error | No defaults — a default turns "unknown" into "known" |
| A name you did not declare | Error | The formula cannot reference it; extra names mean the two sides disagree |
| An account-state name | Error | Its value never leaves the execution plane |
fetch_spec=False skips the fetch, and then only the account-state rule is
checked — the rest is unknowable locally, so it is not pretended. Pass a
PolicySpec yourself via spec= to validate many signals without refetching:
spec = nq.policy_spec_for("my_alpha", ticker="TQQQ")
for bar in bars:
nq.policy_send_signal("my_alpha", ticker="TQQQ", price=bar.close,
direction="buy", params={...}, spec=spec)
policy_spec_for refuses to guess: if several profiles are active on the same
ticker it raises rather than pick one, since their declared parameters can differ.
Pass policy_id= to name the version you mean.
Validation failures raise nq.SignalValidationError.
Two things to keep in mind
The server is always the authority. Passing local validation does not mean the server will accept — policy state and review status live there, not here. This layer exists only to move the obvious mistakes onto your machine, where you can see which field is wrong instead of guessing from a rejection.
There is no publish-time bound on order size. Parameters are names only, with
no declared domain, so nothing proves at publish time that your formula stays under
a limit. How large an order it can place is clamped at order time by the
subscriber's own max_order_cash_usd. Keep your formulas in a sane range yourself.
Requirements
- Python 3.10+
httpx >= 0.27platformdirs >= 4.2
Metadata
Release files for nexusquant-sdk 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nexusquant_sdk-0.2.1.tar.gz | 22.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nexusquant_sdk-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 44.9 kB
Release files / nexusquant_sdk-0.2.1.tar.gz
| Download URL | nexusquant_sdk-0.2.1.tar.gz |
|---|---|
| Size | 22.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7ea0220dc7976d5b32ce6ed502fd3b0a3bd0d044af2ed3ec3f378cdcc646bcf8
|
|
BLAKE2b-256 checksum How to use checksums |
abe93ae421f1eb5c0a74d31fe6da46da3d86b96a8583ce2201ba7815a562ece2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.10 {"installer":{"name":"uv","version":"0.10.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / nexusquant_sdk-0.2.1-py3-none-any.whl
| Download URL | nexusquant_sdk-0.2.1-py3-none-any.whl |
|---|---|
| Size | 22.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
29d6c668e59c52cc5e8fa5a814a80a8a88d184f42fccedcddd8bdb13f2f67977
|
|
BLAKE2b-256 checksum How to use checksums |
5282ea8ae219ae566dfbdea4933563955ee7544453beb6dfa1233156e651c07d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.10 {"installer":{"name":"uv","version":"0.10.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|