Williams %R is a momentum oscillator, developed by Larry Williams, that measures the level of the current close relative to the highest high over a lookback period. It oscillates between -100 and 0 and is used to identify overbought and oversold conditions.
| Parameter | Type | Default | Description |
|---|---|---|---|
period |
int | 14 | Number of periods used to compute the highest high and lowest low |
overboughtThreshold |
float64 | -20 | Threshold above which the market is considered overbought |
oversoldThreshold |
float64 | -80 | Threshold below which the market is considered oversold |
[period, overboughtThreshold?, oversoldThreshold?]
Examples:
[14] // Just period, uses default thresholds (-20, -80)
[14, -20, -80] // Period with standard thresholds
[21, -10, -90] // Longer period with tighter thresholds
The signal’s RawValue field contains a JSON object with the following keys:
| Key | Type | Description |
|---|---|---|
wr |
float64 | The calculated Williams %R value (-100 to 0 scale) |
Example:
{"wr": -55.25}
| Condition | Signal Type | Description |
|---|---|---|
| WR < oversold threshold | SIGNAL_TYPE_BUY_LONG |
Market is oversold, potential buy opportunity |
| WR > overbought threshold | SIGNAL_TYPE_SELL_SHORT |
Market is overbought, potential sell opportunity |
| Otherwise | SIGNAL_TYPE_NO_ACTION |
WR is in neutral zone |
For a lookback period:
high over the last period barslow over the last period barsWhen the range HH - LL is zero (flat market), Williams %R is reported as 0.
func (s *MyStrategy) Initialize(_ context.Context, req *strategy.InitializeRequest) (*emptypb.Empty, error) {
api := strategy.NewStrategyApi()
_, err := api.ConfigureIndicator(context.Background(), &strategy.ConfigureRequest{
IndicatorType: strategy.IndicatorType_INDICATOR_WILLIAMS_R,
Config: `[14, -20, -80]`,
})
if err != nil {
return nil, fmt.Errorf("failed to configure Williams %%R: %w", err)
}
return &emptypb.Empty{}, nil
}
func (s *MyStrategy) ProcessData(ctx context.Context, req *strategy.ProcessDataRequest) (*emptypb.Empty, error) {
data := req.Data
api := strategy.NewStrategyApi()
signal, err := api.GetSignal(ctx, &strategy.GetSignalRequest{
IndicatorType: strategy.IndicatorType_INDICATOR_WILLIAMS_R,
MarketData: data,
})
if err != nil {
return nil, fmt.Errorf("failed to get Williams %%R signal: %w", err)
}
var raw struct {
WR float64 `json:"wr"`
}
if err := json.Unmarshal([]byte(signal.RawValue), &raw); err != nil {
return nil, fmt.Errorf("failed to parse Williams %%R value: %w", err)
}
switch signal.Type {
case strategy.SignalType_SIGNAL_TYPE_BUY_LONG:
fmt.Printf("Williams %%R oversold: %.2f\n", raw.WR)
case strategy.SignalType_SIGNAL_TYPE_SELL_SHORT:
fmt.Printf("Williams %%R overbought: %.2f\n", raw.WR)
default:
fmt.Printf("Williams %%R neutral: %.2f\n", raw.WR)
}
return &emptypb.Empty{}, nil
}
| WR Range | Interpretation |
|---|---|
| -100 to -80 | Oversold - potential buying opportunity |
| -80 to -50 | Bearish momentum, but not oversold |
| -50 | Neutral point |
| -50 to -20 | Bullish momentum, but not overbought |
| -20 to 0 | Overbought - potential selling opportunity |