Guides, manuals and platform references.
Published: 2026-11-11 | Author: AlgoWay
Your Python band sits a little farther from the average than the reference band. The candles match. The lookback matches. Even the multiplier matches. Before blaming the feed, inspect the standard-deviation divisor.
pandas rolling standard deviation defaults to ddof=1, while numpy.std defaults to ddof=0. The result can change an automated trading decision near a band even when both programs receive identical prices. The pandas rolling standard-deviation reference documents the divisor as N - ddof.
For an AlgoWay Python webhook workflow, settle this calculation on the signal side before connecting order delivery. A correctly transmitted instruction can still come from an unintended threshold.
Take the hypothetical completed closes 98, 99, 100, 101 and 102. Their mean is 100. The squared deviations from that mean are 4, 1, 0, 1 and 4, summing to 10.
ddof=0, variance is 10 / 5 = 2. Standard deviation is the square root of 2, about 1.4142.ddof=1, variance is 10 / 4 = 2.5. Standard deviation is about 1.5811.For a band defined as mean plus or minus two standard deviations, the first convention gives approximately 97.1716 and 102.8284. The second gives approximately 96.8377 and 103.1623. The center did not move. The band widened because its divisor shrank.
Suppose a separate decision compares the next observed price, 103, with the upper band frozen from those five completed closes. It is above 102.8284 and below 103.1623. The same observation therefore passes one threshold and fails the other. If your rule instead includes that new observation in a newly calculated window, recalculate both bands; the frozen-band example no longer describes that decision.
This small calculation isolates the setting. It contains no order submission and is not a strategy backtest.
import pandas as pd
close = pd.Series([98.0, 99.0, 100.0, 101.0, 102.0])
window = close.rolling(window=5, min_periods=5)
mid = window.mean()
pop_std = window.std(ddof=0)
sample_std = window.std(ddof=1)
upper_pop = mid + 2 * pop_std
upper_sample = mid + 2 * sample_std
print(round(upper_pop.iloc[-1], 4)) # 102.8284
print(round(upper_sample.iloc[-1], 4)) # 103.1623
NumPy's standard-deviation documentation describes ddof=0 as the population convention. Using ddof=1 applies the familiar sample-variance correction. That correction makes variance an unbiased estimator under the relevant sampling assumptions; taking its square root does not make standard deviation itself unbiased.
Neither label decides which formula belongs in your indicator. When reproducing an existing calculation, match its documented convention. When designing a new rule, specify the convention and evaluate the complete rule. Selecting the wider band after seeing which trades it removes is a new research choice, not a harmless compatibility fix.
For the same nonconstant window of N observations, sample standard deviation divided by population standard deviation equals the square root of N / (N - 1). This follows directly because the sum of squared deviations is shared.
ddof=1.These are changes in band distance, not percentage changes in the asset price. For a constant window with enough observations, both deviations are zero and their ratio is undefined. There is no widening to compare.
A small numerical difference can matter near a strict boundary. It can also make no difference to the decisions in a particular dataset. Inspect the actual condition changes instead of assuming that a visible line difference means a meaningful performance difference.
A matching ddof cannot repair a different set of observations. Compare timestamps and raw closes, including whether the current candle is finished, before comparing the final decimal places. Check whether one implementation uses returns while the other uses price levels; these are different quantities with different units.
Keep min_periods explicit as well. In the example, five observations are required before either band is available. A lower minimum can create early estimates from shorter histories, and missing values introduce a separate eligibility question. The guide to rolling NaN values and missing candles covers that distinction.
For a useful parity check, retain one small window and its mean, squared-deviation sum, observation count, ddof, standard deviation and final threshold. Compare these intermediate values between implementations. Do not round the standard deviation before calculating the band merely to make displayed numbers agree.
Once the arithmetic agrees, the question of what a narrow band actually signals remains separate. Matching a band is a calculation task. Deciding whether its break should open, close or ignore a trade is the trading rule.