sr

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 18, 2026 License: GPL-3.0 Imports: 4 Imported by: 0

README

github.com/laclance/go-sr

go-sr is a standalone Go module for deterministic support/resistance detection and SR-specific multi-timeframe helpers.

Scope

This module owns:

  • Closed-candle SR detection
  • Legacy line-based and zone-based SR modes
  • Deterministic nearest support/resistance metadata
  • SR-specific multi-timeframe helpers for aggregation, warmup sizing, and fetch sizing

This module intentionally does not own:

  • Exchange/Binance parsing
  • Strategy scoring and trade evaluation
  • App-specific timeframe policy like "use 15m and 1h as the higher-timeframe bundles"

Public API

import sr "github.com/laclance/go-sr"

type Mode string

const (
    ModeLegacy Mode = "legacy"
    ModeZones  Mode = "zone"
)

type Options struct {
    Timeframe string
    Lookback  int
    Mode      Mode
    Tolerance float64
}

func Compute(candles []Candle, opts Options) Levels
func EmptyLevels(timeframe string) Levels
func AggregateCandlesToTimeframe(candles []Candle, fromInterval, toInterval string) []Candle
func WarmupCandles(lookback int, mode Mode) int
func RequiredKlineLimit(baseInterval, targetInterval string, lookback int, mode Mode) int

Tolerance applies only to ModeLegacy. When Tolerance <= 0, the fallback remains 0.002.

Behavioral Contract

  • Compute is deterministic for the same candle prefix and options.
  • Zone-mode pivots are confirmation-based; no future candles are read beyond the current prefix.
  • AggregateCandlesToTimeframe uses UTC-aligned buckets and drops leading/trailing partial buckets.
  • RequiredKlineLimit returns the number of raw candles needed to build a higher-timeframe SR bundle and includes one extra live candle for exchange REST responses.
  • Supported interval strings use <n><unit> with m, h, or d, and the target interval must be larger than and evenly divisible by the base interval.

Install

go get github.com/laclance/go-sr

Quick Start

import sr "github.com/laclance/go-sr"

levels := sr.Compute(candles, sr.Options{
    Timeframe: "5m",
    Lookback:  50,
    Mode:      sr.ModeZones,
})

agg15m := sr.AggregateCandlesToTimeframe(candles, "5m", "15m")
levels15m := sr.Compute(agg15m, sr.Options{
    Timeframe: "15m",
    Lookback:  50,
    Mode:      sr.ModeZones,
})

See the runnable examples in examples_test.go for minimal workflows covering zone mode, legacy mode, and multi-timeframe aggregation.

Documentation

Overview

Package sr provides deterministic support/resistance detection for OHLCV candles plus a small set of generic multi-timeframe helpers used to build higher-timeframe SR bundles from a lower-timeframe stream.

The package exposes Candle, PivotInfo, Level, Levels, Mode, Options, Compute, EmptyLevels, AggregateCandlesToTimeframe, WarmupCandles, and RequiredKlineLimit.

Two compute modes are supported:

  • ModeLegacy: line-based pivots with fixed-tolerance proximity
  • ModeZones: zone-based detection with composite scoring and raw/qualified output

The package is intentionally limited to SR detection and SR-specific timeframe helpers. Exchange parsing, app-specific timeframe policy, strategy scoring, and trade evaluation remain outside this package.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func RequiredKlineLimit

func RequiredKlineLimit(baseInterval, targetInterval string, lookback int, mode Mode) int

RequiredKlineLimit returns the raw kline fetch size needed to build an S/R bundle for targetInterval from a baseInterval stream. The returned size includes one extra live candle because exchange REST responses usually include the currently forming bar.

func WarmupCandles

func WarmupCandles(lookback int, mode Mode) int

WarmupCandles returns the minimum closed-candle history needed before a support/resistance calculation can be considered fully warmed up.

Types

type Candle

type Candle struct {
	OpenTime  time.Time
	CloseTime time.Time
	Open      float64
	High      float64
	Low       float64
	Close     float64
	Volume    float64
}

Candle represents a single OHLCV closed candlestick.

func AggregateCandlesToTimeframe

func AggregateCandlesToTimeframe(candles []Candle, fromInterval, toInterval string) []Candle

AggregateCandlesToTimeframe rolls a closed-candle slice into a higher timeframe using UTC-aligned buckets. Any leading or trailing partial bucket is dropped.

Example
start := time.Date(2024, 4, 1, 0, 0, 0, 0, time.UTC)
candles := make5mCandles(start, []struct {
	open   float64
	high   float64
	low    float64
	close  float64
	volume float64
}{
	{100, 101, 99, 100.5, 10},
	{100.5, 102, 100, 101.5, 20},
	{101.5, 103, 101, 102.5, 30},
})

agg := AggregateCandlesToTimeframe(candles, "5m", "15m")
fmt.Println(len(agg), agg[0].Open, agg[0].Close, agg[0].Volume)
Output:
1 100 102.5 60

func (Candle) Body

func (c Candle) Body() float64

func (Candle) IsBearish

func (c Candle) IsBearish() bool

func (Candle) IsBullish

func (c Candle) IsBullish() bool

func (Candle) LowerWick

func (c Candle) LowerWick() float64

func (Candle) MidPoint

func (c Candle) MidPoint() float64

func (Candle) Range

func (c Candle) Range() float64

func (Candle) UpperWick

func (c Candle) UpperWick() float64

type Level

type Level struct {
	Price              float64
	Top                float64
	Bottom             float64
	Strength           int
	Score              float64
	IsHigh             bool
	Timeframe          string
	LastTouchIndex     int
	SourcePivotIndexes []int
	Pivots             []PivotInfo
}

Level represents a support or resistance zone built from clustered swing pivots.

type Levels

type Levels struct {
	Timeframe string

	Levels                    []Level
	RawZones                  []Level
	NearSupport               bool
	NearResistance            bool
	NearestSupport            float64
	NearestResistance         float64
	NearestSupportDistance    float64
	NearestResistanceDistance float64
	NearestSupportStrength    int
	NearestResistanceStrength int
	NearestSupportScore       float64
	NearestResistanceScore    float64
}

Levels holds computed support/resistance data for the current candle series.

func Compute

func Compute(candles []Candle, opts Options) Levels

Compute detects support/resistance levels for the given candle prefix.

Example (Legacy)
levels := Compute(buildSRCategoryCandles(), Options{
	Timeframe: "5m",
	Lookback:  120,
	Mode:      ModeLegacy,
	Tolerance: 0.002,
})

fmt.Println(levels.Timeframe, len(levels.Levels) >= 2, levels.NearestSupport > 0, levels.NearestResistance > 0)
Output:
5m true true true
Example (Zone)
levels := Compute(buildSRCategoryCandles(), Options{
	Timeframe: "5m",
	Lookback:  120,
	Mode:      ModeZones,
})

fmt.Println(levels.Timeframe, len(levels.Levels) >= 2, levels.NearestSupport > 0, levels.NearestResistance > 0)
Output:
5m true true true

func EmptyLevels

func EmptyLevels(timeframe string) Levels

EmptyLevels returns the zero-value bundle for a timeframe label.

type Mode

type Mode string

Mode selects the support/resistance algorithm.

const (
	ModeLegacy Mode = "legacy"
	ModeZones  Mode = "zone"
)

type Options

type Options struct {
	Timeframe string
	Lookback  int
	Mode      Mode
	Tolerance float64
	// MinStrength filters zone-mode raw zones by Strength.
	// 0 or negative -> use the default of 2 (back-compat).
	// 1+           -> require Strength >= MinStrength.
	// No effect on Mode=Legacy.
	MinStrength int
}

Options configures a support/resistance computation.

type PivotInfo

type PivotInfo struct {
	Index             int       `json:"index"`
	ConfirmedAtIndex  int       `json:"confirmed_at_index"`
	Time              time.Time `json:"time"`
	Price             float64   `json:"price"`
	IsHigh            bool      `json:"is_high"`
	Timeframe         string    `json:"timeframe"`
	ATRSnapshot       float64   `json:"atr_snapshot"`
	AvgVolumeSnapshot float64   `json:"avg_volume_snapshot"`
	Volume            float64   `json:"volume"`
	VolumeRatio       float64   `json:"volume_ratio"`
	MergeWidth        float64   `json:"merge_width"`
	BounceATR         float64   `json:"bounce_atr"`
}

PivotInfo captures the local snapshot data used to build a support or resistance zone.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL