The same indicator, two different answers — which is right?
Both. That is the problem.
One ticker, one day, two moving averages
Two calls to /technical/{ticker} differing in one parameter — /technical/AAPL.US?function=sma&period=50 and /technical/AAPL.US?function=sma&period=200 — for 2026-07-27, with a close of 336.91:
sma, period=50 306.9922
sma, period=200 276.0692
Same function, same symbol, same day. The two differ by 30.9230 points, which is 11.20% of the 200-day value. The close sits 9.75% above the 50-day average and 22.04% above the 200-day one.
So the sentence "the stock is above its moving average" is not a fact until you say which one — and the sentence "it is 10% above trend" and "it is 22% above trend" are both defensible descriptions of the same day. A stored indicator value without its parameters is not data; it is a number.
Every knob that changes the answer
period— an integer from 2 to 100,000, defaulting to 50. The default is a convention, not a recommendation, and it silently becomes your assumption if you never pass the parameter.- MACD's three periods — fast, slow and signal. The 8.9310 above came from 12, 26 and 9. Other triples give other numbers, and none is canonical.
- Stochastic and StochRSI carry their own fast and slow K and D periods; SAR carries an acceleration and a maximum; beta needs a second symbol, because a beta without a named benchmark is not a quantity at all.
fromandtoasYYYY-MM-DD,orderasaord(defaulta),fmtasjsonorcsv(defaultjson).splitadjusted_only, 0 or 1 — the subject of the next lesson.filter— the specification documentslast_emaandlast_volumefor returning a single scalar instead of a series. In practicelast_sma,last_rsi,last_macd,last_atrandlast_adxall returned single values too, which is how several numbers in this unit were fetched. Convenient, and worth naming for what it is: undocumented behaviour that works today is a dependency you did not sign for. If you rely on it, write a test that fails loudly when it stops.
Units, and a familiar trap
Three more values from the same day: RSI(14) = 67.2912, ADX(14) = 27.6999, ATR(14) = 8.1406.
The first two are already dimensionless — RSI is bounded 0 to 100, ADX is an index. ATR is not: 8.1406 is in dollars. Against a close of 336.91 that is 2.42% of price. Compare a raw ATR of 8.14 on one stock with 0.80 on another and you have compared price levels, not volatility. Divide by price first.
This is exactly the pip-versus-percentage lesson from the Foreign Exchange course, arriving in a new market: a number in price units is not comparable across instruments until you normalise it.
Knobs that do nothing, and defaults nobody chose
Four behaviours, each checked against AAPL.US on 29 September 2026, and none of them raises an error.
stochasticignoresperiod. Its windows arefast_kperiod,slow_kperiodandslow_dperiod. A bare call, a call withperiod=14and a call with 14, 3 and 3 spelled out returned identicalk_valuesandd_values, becauseperiodis not one of its parameters and is dropped silently.betapicks both the benchmark and the window.code2defaults toGSPC.INDX. Withoutfromthe function works over its own window of roughly the last 250 sessions and takesperiodout of the start of it, soperiod=250left a single row andperiod=300returned200and an empty array. Passfromand the series reaches back as far as you ask.stddevsends its warm-up rows. Wheresmasimply omits its warm-up bars,stddevreturns its own, fifty of them atperiod=50, with the booleanfalsein place of a number, which most parsers turn into 0 without complaint. A window shorter thanperiodcomes back as nothing butfalse. And like ATR it is in price units: dollars of scatter, not a percentage.emastarts from ansma. Its first row is the simple average of the first window, identical to thesmafor the same date and period; the exponential weighting only begins on the row after.
The discipline this implies
Store indicator values as a full tuple: function, ticker, date, every parameter, and the value. Not sma_value. The moment one series in your warehouse holds a value whose period nobody recorded, it is unusable — and you will not find out for months, because it will keep plotting perfectly.
What any of these numbers mean belongs to the Technical Analysis domain, which teaches them properly. This lesson only insists that you can say which number you fetched.
Try it now
- Fetch
/technical/{ticker}?function=sma&period=20, then the same call atperiod=50andperiod=200, for one symbol on the same date. Write the three values next to the close and see how many different true sentences you can form.
- Here is
/technical/AAPL.US?function=macdtwice for the same day, 25 September 2026: once with no periods sent, which is 12, 26 and 9, and once withfast_period=5&slow_period=35&signal_period=5. Compare the three fields, and say which reading of momentum each one invites. Then look at whichever charting tool you use and find out which triple it silently assumed.
- Here is ATR(14) on 25 September 2026 for three instruments at very different price levels, Apple, Ford and NVR, and their closes that day in one bulk call. Divide each ATR by its close. Rank them by raw ATR and by the ratio. The two rankings will not match, and the second is the one that means something.
- Four checks on the section above. The first two tables are Apple's stochastic over the same window, once with nothing sent and once with
period=14: compare them. The third is a 50-periodstddevfrom the first trading day of 2026: find the first row that holds a number, count the rows before it and say what your parser did with them. The fourth isbetawith nofromand noperiod: read the first date and say how far back the window reached and what it was measured against. The last two areemaandsmaover one window: compare their first rows, then their second.