The idea
“Everyone has a plan until they get punched in the mouth.” Mike Tyson.
I love this quote from Iron Mike. It captures a universal truth about the gap between theory and contact with reality. A plan is made in calm conditions, full information, zero pressure, and an imagined version of how events will unfold. Reality never cooperates.
The quote isn’t really an argument against planning. The ability to absorb the hit, stay composed, and adapt, rather than freezing when the script gets torn up, is at least as valuable as the plan itself. That’s the lesson.
Every serious quant operation has some kind of incubation process. Some kind of forward testing (either by paper trading or, if possible, by live trading with a small account)… the specific details don’t matter. What matters is exposing the strategy to live conditions before scaling it.
This week, I have an invitation for all subscribers who support quantitativo.com: let’s incubate the triangulated stat arb strategy described in the last article together! To do it, I’m streaming the live signal to all paid subscribers. Today’s article details how to get the live signal.
The API
The API serves the triangulated stat arb live signal from the last article over plain HTTPS + JSON. Base URL:
https://signals.quantitativo.com/api/v1Everything is a GET you can poll (there are no webhooks or streams), authenticated with a personal API key in a header. The signal is updated every 5 minutes through the US session.
Get your API key
Getting your API key is simple:
curl -X POST https://signals.quantitativo.com/api/v1/keys/request -d email=you@example.comThe body can be form-encoded (as above) or JSON ({”email”: “you@example.com”}). If the email has an active paid subscription, the key arrives by email within a minute. The response is always the same 202 either way (so the endpoint confirms nothing about who subscribes).
{"message": "If this email has an active subscription, your API key is on its way."}Authentication
Every data endpoint requires the key in the Authorization header. The header is the only place a key is read from (never a query parameter, so keys stay out of URLs and logs):
curl -H "Authorization: Bearer qs_YOUR_KEY" https://signals.quantitativo.com/api/v1/signalsEndpoints
GET /signals: what is published, and how fresh
{"signals": [{"signal": "tsa",
"as_of": "2026-08-31T17:00:00+00:00",
"published_at": "2026-08-31T17:00:03.028970+00:00"}]}The cheapest freshness probe: one row per signal with the latest observation’s as_of.
GET /signals/{code}/latest: the current observation
curl -H "Authorization: Bearer qs_YOUR_KEY" https://signals.quantitativo.com/api/v1/signals/tsa/latest{
"signal": "tsa",
"as_of": "2026-08-31T17:00:00+00:00",
"published_at": "2026-08-31T17:00:03.028970+00:00",
"date": "2026-08-31",
"now_et": "2026-08-31T13:00:00-04:00",
"latest_bar_end": "2026-08-31T12:59:00-04:00",
"next_update_at": "2026-08-31T13:05:00-04:00",
"n_pairs": 2291, "n_legs": 1662, "n_vote_network": 1606,
"rows": [
{"ticker": "CYTK", "signal": -1.8861, "depth": 12, "consistency": 1.0},
{"ticker": "NAMS", "signal": -1.8255, "depth": 4, "consistency": 1.0},
{"ticker": "AURA", "signal": -1.7969, "depth": 9, "consistency": 0.75},
...
]
}as_of: the observation’s 5-minute slot on the market clock (UTC). The key: a newas_ofis a new observation; the sameas_ofre-served is the same one.rows: the eligible names, sorted bysignalascending. Per name:signal(the aggregated triangulation score),depth(how many selected pairs voted on the name) andconsistency(the share of those votes agreeing in direction). Only eligible names are published (depth and consistency thresholds). For what the score means and how the book is built, see the newsletter’s articles on the strategy.next_update_at: the next slot (ET); don’t poll again before it.dateis the trading day,latest_bar_endthe newest price bar in the computation. Timestamps are ISO 8601 with explicit offsets:as_ofandpublished_atin UTC, the_et/market fields with their ET offset; parse the offset and any library compares them correctly.
Add ?debug=1 for the run’s diagnostics.
Once you have the data, it’s trivial to visualize it:
GET /health: service status, no key needed
200 with {"status": "ok", ...} when the service is doing its job, 503 with the reasons when it is not. If your script sees errors, check this first: it distinguishes “the service has a problem” from “my script has a problem”.
Errors
Errors always have this shape, and code is the stable contract to branch on (messages may change, codes will not):
{"error": {"code": "rate_limited", "message": "Rate limit of 60 requests per minute exceeded."}}A polling loop that behaves
New observations appear only during the session (roughly 05:00-20:55 ET, Mon-Fri, US market holidays excluded), and a quiet stretch with no new prints publishes nothing. So as_of can legitimately skip slots and stand still overnight and on weekends. Poll latest about once a minute at most; act only when as_of changes:
import time
import requests
BASE = "https://signals.quantitativo.com/api/v1"
HEADERS = {"Authorization": "Bearer qs_YOUR_KEY"}
last_as_of = None
while True:
response = requests.get(f"{BASE}/signals/tsa/latest", headers=HEADERS, timeout=30)
if response.status_code == 429:
time.sleep(int(response.headers.get("Retry-After", 60)))
continue
if response.status_code != 200:
code = response.json()["error"]["code"] # branch on the code, not the message
raise RuntimeError(f"API error: {code}")
latest = response.json()
if latest["as_of"] != last_as_of:
last_as_of = latest["as_of"]
for row in latest["rows"]:
... # your logic
time.sleep(60)A place to explore ideas
As many of you already know, we have a private community to explore ideas, exchange insights, and tackle the real technical and strategic challenges of building trading systems. Let’s use that space to discuss the implementation details of this strategy.
If you are a paid subscriber and want to join, just email me (cs@quantitativo.com), and I will send the keys.
Final thoughts
I really enjoy talking to the subscribers. As I’ve mentioned over and over, I’ve met amazing people all over the world, some of the smartest people I’ve come across. And I’ve made good friends in the process.
In one of these calls last week, I met this pretty smart scientist. He told me he had implemented and verified a strategy I’d written about a while ago, and was successfully trading it. But one thing caught my attention: he said it took him months to finish it.
Why did it take such a smart guy so long to complete the implementation? I thought. But then I remembered how long it took me to build my base infrastructure, which I can now leverage.
If someone decides to implement a strategy like this one starting from zero infrastructure, it might indeed take them many months to finish. So, why not test the live signal first? Why not receive the streamed signal and see how it behaves live before committing to building the whole thing? I think it might make sense. But I know nothing… You tell me :)
This is an experiment. If you find it useful, I will add more signals to the API.
This community has been so good to me that this is the least I can do :)
As always, I’d love to hear your thoughts. Feel free to reach out via Twitter or email if you have questions, ideas, or feedback.
Cheers!





