// Code generated from bindings/c/include/wickra.h. DO NOT EDIT.

package wickra

/*
#include <stdlib.h>
#include "wickra.h"
*/
import "C"

import (
	"runtime"
	"time"
	"unsafe"
)

// Keep the unsafe import live even if no archetype in a given build uses
// a slice pointer (every real header does).
var _ = unsafe.Pointer(nil)

// AccelerationBandsOutput is the output of the AccelerationBands indicator.
type AccelerationBandsOutput struct {
	Upper  float64
	Middle float64
	Lower  float64
}

// AdxOutput is the output of the Adx indicator.
type AdxOutput struct {
	PlusDi  float64
	MinusDi float64
	Adx     float64
}

// AlligatorOutput is the output of the Alligator indicator.
type AlligatorOutput struct {
	Jaw   float64
	Teeth float64
	Lips  float64
}

// AndrewsPitchforkOutput is the output of the AndrewsPitchfork indicator.
type AndrewsPitchforkOutput struct {
	Median float64
	Upper  float64
	Lower  float64
}

// AroonOutput is the output of the Aroon indicator.
type AroonOutput struct {
	Up   float64
	Down float64
}

// AtrBandsOutput is the output of the AtrBands indicator.
type AtrBandsOutput struct {
	Upper  float64
	Middle float64
	Lower  float64
}

// AtrRatchetOutput is the output of the AtrRatchet indicator.
type AtrRatchetOutput struct {
	Value     float64
	Direction float64
}

// AutoFibOutput is the output of the AutoFib indicator.
type AutoFibOutput struct {
	Level0    float64
	Level236  float64
	Level382  float64
	Level500  float64
	Level618  float64
	Level786  float64
	Level1000 float64
}

// BollingerOutput is the output of the Bollinger indicator.
type BollingerOutput struct {
	Upper  float64
	Middle float64
	Lower  float64
	Stddev float64
}

// BomarBandsOutput is the output of the BomarBands indicator.
type BomarBandsOutput struct {
	Upper  float64
	Middle float64
	Lower  float64
}

// CamarillaPivotsOutput is the output of the CamarillaPivots indicator.
type CamarillaPivotsOutput struct {
	Pp float64
	R1 float64
	R2 float64
	R3 float64
	R4 float64
	S1 float64
	S2 float64
	S3 float64
	S4 float64
}

// Candle is the output of the Candle indicator.
type Candle struct {
	Open      float64
	High      float64
	Low       float64
	Close     float64
	Volume    float64
	Timestamp int64
}

// CandleVolumeOutput is the output of the CandleVolume indicator.
type CandleVolumeOutput struct {
	Body  float64
	Width float64
}

// CentralPivotRangeOutput is the output of the CentralPivotRange indicator.
type CentralPivotRangeOutput struct {
	Pivot float64
	Tc    float64
	Bc    float64
}

// ChandeKrollStopOutput is the output of the ChandeKrollStop indicator.
type ChandeKrollStopOutput struct {
	StopLong  float64
	StopShort float64
}

// ChandelierExitOutput is the output of the ChandelierExit indicator.
type ChandelierExitOutput struct {
	LongStop  float64
	ShortStop float64
}

// ClassicPivotsOutput is the output of the ClassicPivots indicator.
type ClassicPivotsOutput struct {
	Pp float64
	R1 float64
	R2 float64
	R3 float64
	S1 float64
	S2 float64
	S3 float64
}

// CointegrationOutput is the output of the Cointegration indicator.
type CointegrationOutput struct {
	HedgeRatio float64
	Spread     float64
	AdfStat    float64
}

// CompositeProfileOutput is the output of the CompositeProfile indicator.
type CompositeProfileOutput struct {
	Poc float64
	Vah float64
	Val float64
}

// DemarkPivotsOutput is the output of the DemarkPivots indicator.
type DemarkPivotsOutput struct {
	Pp float64
	R1 float64
	S1 float64
}

// DollarBar is the output of the DollarBar indicator.
type DollarBar struct {
	Open   float64
	High   float64
	Low    float64
	Close  float64
	Volume float64
	Dollar float64
}

// DonchianOutput is the output of the Donchian indicator.
type DonchianOutput struct {
	Upper  float64
	Middle float64
	Lower  float64
}

// DonchianStopOutput is the output of the DonchianStop indicator.
type DonchianStopOutput struct {
	StopLong  float64
	StopShort float64
}

// DoubleBollingerOutput is the output of the DoubleBollinger indicator.
type DoubleBollingerOutput struct {
	UpperOuter float64
	UpperInner float64
	Middle     float64
	LowerInner float64
	LowerOuter float64
}

// ElderRayOutput is the output of the ElderRay indicator.
type ElderRayOutput struct {
	BullPower float64
	BearPower float64
}

// ElderSafeZoneOutput is the output of the ElderSafeZone indicator.
type ElderSafeZoneOutput struct {
	Value     float64
	Direction float64
}

// EquivolumeOutput is the output of the Equivolume indicator.
type EquivolumeOutput struct {
	Height float64
	Width  float64
}

// FibArcsOutput is the output of the FibArcs indicator.
type FibArcsOutput struct {
	Arc382 float64
	Arc500 float64
	Arc618 float64
}

// FibChannelOutput is the output of the FibChannel indicator.
type FibChannelOutput struct {
	Base      float64
	Level618  float64
	Level1000 float64
	Level1618 float64
}

// FibConfluenceOutput is the output of the FibConfluence indicator.
type FibConfluenceOutput struct {
	Price    float64
	Strength float64
}

// FibExtensionOutput is the output of the FibExtension indicator.
type FibExtensionOutput struct {
	Level1272 float64
	Level1414 float64
	Level1618 float64
	Level2000 float64
	Level2618 float64
}

// FibFanOutput is the output of the FibFan indicator.
type FibFanOutput struct {
	Fan382 float64
	Fan500 float64
	Fan618 float64
}

// FibProjectionOutput is the output of the FibProjection indicator.
type FibProjectionOutput struct {
	Level618  float64
	Level1000 float64
	Level1618 float64
	Level2618 float64
}

// FibRetracementOutput is the output of the FibRetracement indicator.
type FibRetracementOutput struct {
	Level0    float64
	Level236  float64
	Level382  float64
	Level500  float64
	Level618  float64
	Level786  float64
	Level1000 float64
}

// FibTimeZonesOutput is the output of the FibTimeZones indicator.
type FibTimeZonesOutput struct {
	OnZone     float64
	BarsToNext float64
}

// FibonacciPivotsOutput is the output of the FibonacciPivots indicator.
type FibonacciPivotsOutput struct {
	Pp float64
	R1 float64
	R2 float64
	R3 float64
	S1 float64
	S2 float64
	S3 float64
}

// FootprintLevel is the output of the FootprintLevel indicator.
type FootprintLevel struct {
	Price  float64
	BidVol float64
	AskVol float64
}

// FractalChaosBandsOutput is the output of the FractalChaosBands indicator.
type FractalChaosBandsOutput struct {
	Upper float64
	Lower float64
}

// GatorOscillatorOutput is the output of the GatorOscillator indicator.
type GatorOscillatorOutput struct {
	Upper float64
	Lower float64
}

// GoldenPocketOutput is the output of the GoldenPocket indicator.
type GoldenPocketOutput struct {
	Low  float64
	Mid  float64
	High float64
}

// HeikinAshiOutput is the output of the HeikinAshi indicator.
type HeikinAshiOutput struct {
	Open  float64
	High  float64
	Low   float64
	Close float64
}

// HighLowVolumeNodesOutput is the output of the HighLowVolumeNodes indicator.
type HighLowVolumeNodesOutput struct {
	Hvn float64
	Lvn float64
}

// HtPhasorOutput is the output of the HtPhasor indicator.
type HtPhasorOutput struct {
	Inphase    float64
	Quadrature float64
}

// HurstChannelOutput is the output of the HurstChannel indicator.
type HurstChannelOutput struct {
	Upper  float64
	Middle float64
	Lower  float64
}

// IchimokuOutput is the output of the Ichimoku indicator.
type IchimokuOutput struct {
	Tenkan  float64
	Kijun   float64
	SenkouA float64
	SenkouB float64
	Chikou  float64
}

// ImbalanceBar is the output of the ImbalanceBar indicator.
type ImbalanceBar struct {
	Open      float64
	High      float64
	Low       float64
	Close     float64
	Imbalance float64
	Direction int8
}

// InitialBalanceOutput is the output of the InitialBalance indicator.
type InitialBalanceOutput struct {
	High float64
	Low  float64
}

// KagiBar is the output of the KagiBar indicator.
type KagiBar struct {
	Start     float64
	End       float64
	Direction int8
}

// KalmanHedgeRatioOutput is the output of the KalmanHedgeRatio indicator.
type KalmanHedgeRatioOutput struct {
	HedgeRatio float64
	Intercept  float64
	Spread     float64
}

// KaseDevStopOutput is the output of the KaseDevStop indicator.
type KaseDevStopOutput struct {
	Value     float64
	Direction float64
}

// KasePermissionStochasticOutput is the output of the KasePermissionStochastic indicator.
type KasePermissionStochasticOutput struct {
	Fast float64
	Slow float64
}

// KeltnerOutput is the output of the Keltner indicator.
type KeltnerOutput struct {
	Upper  float64
	Middle float64
	Lower  float64
}

// KstOutput is the output of the Kst indicator.
type KstOutput struct {
	Kst    float64
	Signal float64
}

// LeadLagCrossCorrelationOutput is the output of the LeadLagCrossCorrelation indicator.
type LeadLagCrossCorrelationOutput struct {
	Lag         int64
	Correlation float64
}

// LinRegChannelOutput is the output of the LinRegChannel indicator.
type LinRegChannelOutput struct {
	Upper  float64
	Middle float64
	Lower  float64
}

// LineBreakBar is the output of the LineBreakBar indicator.
type LineBreakBar struct {
	Open      float64
	Close     float64
	Direction int8
}

// LiquidationFeaturesOutput is the output of the LiquidationFeatures indicator.
type LiquidationFeaturesOutput struct {
	Long      float64
	Short     float64
	Net       float64
	Total     float64
	Imbalance float64
}

// MaEnvelopeOutput is the output of the MaEnvelope indicator.
type MaEnvelopeOutput struct {
	Upper  float64
	Middle float64
	Lower  float64
}

// MacdOutput is the output of the Macd indicator.
type MacdOutput struct {
	Macd      float64
	Signal    float64
	Histogram float64
}

// MamaOutput is the output of the Mama indicator.
type MamaOutput struct {
	Mama float64
	Fama float64
}

// MedianChannelOutput is the output of the MedianChannel indicator.
type MedianChannelOutput struct {
	Upper  float64
	Middle float64
	Lower  float64
}

// ModifiedMaStopOutput is the output of the ModifiedMaStop indicator.
type ModifiedMaStopOutput struct {
	Value     float64
	Direction float64
}

// MurreyMathLinesOutput is the output of the MurreyMathLines indicator.
type MurreyMathLinesOutput struct {
	Mm88 float64
	Mm78 float64
	Mm68 float64
	Mm58 float64
	Mm48 float64
	Mm38 float64
	Mm28 float64
	Mm18 float64
	Mm08 float64
}

// NrtrOutput is the output of the Nrtr indicator.
type NrtrOutput struct {
	Value     float64
	Direction float64
}

// OpeningRangeOutput is the output of the OpeningRange indicator.
type OpeningRangeOutput struct {
	High             float64
	Low              float64
	BreakoutDistance float64
}

// OvernightIntradayReturnOutput is the output of the OvernightIntradayReturn indicator.
type OvernightIntradayReturnOutput struct {
	Overnight float64
	Intraday  float64
}

// PnfColumn is the output of the PnfColumn indicator.
type PnfColumn struct {
	Direction int8
	High      float64
	Low       float64
}

// ProjectionBandsOutput is the output of the ProjectionBands indicator.
type ProjectionBandsOutput struct {
	Upper  float64
	Middle float64
	Lower  float64
}

// QqeOutput is the output of the Qqe indicator.
type QqeOutput struct {
	RsiMa        float64
	TrailingLine float64
}

// QuartileBandsOutput is the output of the QuartileBands indicator.
type QuartileBandsOutput struct {
	Upper  float64
	Middle float64
	Lower  float64
}

// RangeBar is the output of the RangeBar indicator.
type RangeBar struct {
	Open      float64
	Close     float64
	Direction int8
}

// RelativeStrengthOutput is the output of the RelativeStrength indicator.
type RelativeStrengthOutput struct {
	Ratio    float64
	RatioMa  float64
	RatioRsi float64
}

// RenkoBrick is the output of the RenkoBrick indicator.
type RenkoBrick struct {
	Open      float64
	Close     float64
	Direction int8
}

// RunBar is the output of the RunBar indicator.
type RunBar struct {
	Open      float64
	High      float64
	Low       float64
	Close     float64
	Length    int
	Direction int8
}

// RwiOutput is the output of the Rwi indicator.
type RwiOutput struct {
	High float64
	Low  float64
}

// SessionHighLowOutput is the output of the SessionHighLow indicator.
type SessionHighLowOutput struct {
	High float64
	Low  float64
}

// SessionRangeOutput is the output of the SessionRange indicator.
type SessionRangeOutput struct {
	Asia float64
	Eu   float64
	Us   float64
}

// SmoothedHeikinAshiOutput is the output of the SmoothedHeikinAshi indicator.
type SmoothedHeikinAshiOutput struct {
	Open  float64
	High  float64
	Low   float64
	Close float64
}

// SpreadBollingerBandsOutput is the output of the SpreadBollingerBands indicator.
type SpreadBollingerBandsOutput struct {
	Middle   float64
	Upper    float64
	Lower    float64
	PercentB float64
}

// StandardErrorBandsOutput is the output of the StandardErrorBands indicator.
type StandardErrorBandsOutput struct {
	Upper  float64
	Middle float64
	Lower  float64
}

// StarcBandsOutput is the output of the StarcBands indicator.
type StarcBandsOutput struct {
	Upper  float64
	Middle float64
	Lower  float64
}

// StochasticOutput is the output of the Stochastic indicator.
type StochasticOutput struct {
	K float64
	D float64
}

// SuperTrendOutput is the output of the SuperTrend indicator.
type SuperTrendOutput struct {
	Value     float64
	Direction float64
}

// TdLinesOutput is the output of the TdLines indicator.
type TdLinesOutput struct {
	Resistance float64
	Support    float64
}

// TdMovingAverageOutput is the output of the TdMovingAverage indicator.
type TdMovingAverageOutput struct {
	St1 float64
	St2 float64
}

// TdRangeProjectionOutput is the output of the TdRangeProjection indicator.
type TdRangeProjectionOutput struct {
	High float64
	Low  float64
}

// TdRiskLevelOutput is the output of the TdRiskLevel indicator.
type TdRiskLevelOutput struct {
	BuyRisk  float64
	SellRisk float64
}

// TdSequentialOutput is the output of the TdSequential indicator.
type TdSequentialOutput struct {
	Setup     float64
	Countdown float64
	Direction float64
}

// TickBar is the output of the TickBar indicator.
type TickBar struct {
	Open   float64
	High   float64
	Low    float64
	Close  float64
	Volume float64
}

// TpoProfileOutputScalars is the output of the TpoProfileOutputScalars indicator.
type TpoProfileOutputScalars struct {
	PriceLow  float64
	PriceHigh float64
	Values    []float64
}

// TtmSqueezeOutput is the output of the TtmSqueeze indicator.
type TtmSqueezeOutput struct {
	Squeeze  float64
	Momentum float64
}

// ValueAreaOutput is the output of the ValueArea indicator.
type ValueAreaOutput struct {
	Poc float64
	Vah float64
	Val float64
}

// VolatilityConeOutput is the output of the VolatilityCone indicator.
type VolatilityConeOutput struct {
	Current    float64
	Min        float64
	Median     float64
	Max        float64
	Percentile float64
}

// VolumeBar is the output of the VolumeBar indicator.
type VolumeBar struct {
	Open   float64
	High   float64
	Low    float64
	Close  float64
	Volume float64
}

// VolumeProfileOutputScalars is the output of the VolumeProfileOutputScalars indicator.
type VolumeProfileOutputScalars struct {
	PriceLow  float64
	PriceHigh float64
	Values    []float64
}

// VolumeWeightedMacdOutput is the output of the VolumeWeightedMacd indicator.
type VolumeWeightedMacdOutput struct {
	Macd      float64
	Signal    float64
	Histogram float64
}

// VolumeWeightedSrOutput is the output of the VolumeWeightedSr indicator.
type VolumeWeightedSrOutput struct {
	Support    float64
	Resistance float64
}

// VortexOutput is the output of the Vortex indicator.
type VortexOutput struct {
	Plus  float64
	Minus float64
}

// VwapStdDevBandsOutput is the output of the VwapStdDevBands indicator.
type VwapStdDevBandsOutput struct {
	Upper  float64
	Middle float64
	Lower  float64
	Stddev float64
}

// WaveTrendOutput is the output of the WaveTrend indicator.
type WaveTrendOutput struct {
	Wt1 float64
	Wt2 float64
}

// WilliamsFractalsOutput is the output of the WilliamsFractals indicator.
type WilliamsFractalsOutput struct {
	Up   float64
	Down float64
}

// WoodiePivotsOutput is the output of the WoodiePivots indicator.
type WoodiePivotsOutput struct {
	Pp float64
	R1 float64
	R2 float64
	S1 float64
	S2 float64
}

// ZeroLagMacdOutput is the output of the ZeroLagMacd indicator.
type ZeroLagMacdOutput struct {
	Macd      float64
	Signal    float64
	Histogram float64
}

// ZigZagOutput is the output of the ZigZag indicator.
type ZigZagOutput struct {
	Swing     float64
	Direction float64
}

// AbandonedBaby wraps the AbandonedBaby indicator over the Wickra C ABI.
type AbandonedBaby struct {
	handle *C.struct_AbandonedBaby
}

// NewAbandonedBaby constructs a AbandonedBaby. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAbandonedBaby() (*AbandonedBaby, error) {
	ptr := C.wickra_abandoned_baby_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AbandonedBaby{handle: ptr}
	runtime.SetFinalizer(obj, (*AbandonedBaby).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AbandonedBaby) WarmupPeriod() int {
	r := int(C.wickra_abandoned_baby_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AbandonedBaby) IsReady() bool {
	r := bool(C.wickra_abandoned_baby_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AbandonedBaby) Name() string {
	r := C.GoString(C.wickra_abandoned_baby_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *AbandonedBaby) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_abandoned_baby_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *AbandonedBaby) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_abandoned_baby_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AbandonedBaby) Reset() {
	C.wickra_abandoned_baby_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AbandonedBaby) Close() {
	if ind.handle != nil {
		C.wickra_abandoned_baby_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Abcd wraps the Abcd indicator over the Wickra C ABI.
type Abcd struct {
	handle *C.struct_Abcd
}

// NewAbcd constructs a Abcd. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAbcd() (*Abcd, error) {
	ptr := C.wickra_abcd_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Abcd{handle: ptr}
	runtime.SetFinalizer(obj, (*Abcd).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Abcd) WarmupPeriod() int {
	r := int(C.wickra_abcd_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Abcd) IsReady() bool {
	r := bool(C.wickra_abcd_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Abcd) Name() string {
	r := C.GoString(C.wickra_abcd_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Abcd) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_abcd_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Abcd) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_abcd_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Abcd) Reset() {
	C.wickra_abcd_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Abcd) Close() {
	if ind.handle != nil {
		C.wickra_abcd_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AbsoluteBreadthIndex wraps the AbsoluteBreadthIndex indicator over the Wickra C ABI.
type AbsoluteBreadthIndex struct {
	handle *C.struct_AbsoluteBreadthIndex
}

// NewAbsoluteBreadthIndex constructs a AbsoluteBreadthIndex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAbsoluteBreadthIndex() (*AbsoluteBreadthIndex, error) {
	ptr := C.wickra_absolute_breadth_index_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AbsoluteBreadthIndex{handle: ptr}
	runtime.SetFinalizer(obj, (*AbsoluteBreadthIndex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AbsoluteBreadthIndex) WarmupPeriod() int {
	r := int(C.wickra_absolute_breadth_index_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AbsoluteBreadthIndex) IsReady() bool {
	r := bool(C.wickra_absolute_breadth_index_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AbsoluteBreadthIndex) Name() string {
	r := C.GoString(C.wickra_absolute_breadth_index_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *AbsoluteBreadthIndex) Update(change []float64, volume []float64, newHigh []bool, newLow []bool, aboveMa []bool, onBuySignal []bool, timestamp int64) float64 {
	if len(volume) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newHigh) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newLow) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(aboveMa) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(onBuySignal) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_absolute_breadth_index_update(ind.handle, (*C.double)(unsafe.Pointer(&change[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.bool)(unsafe.Pointer(&newHigh[0])), (*C.bool)(unsafe.Pointer(&newLow[0])), (*C.bool)(unsafe.Pointer(&aboveMa[0])), (*C.bool)(unsafe.Pointer(&onBuySignal[0])), C.uintptr_t(len(change)), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(change)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(newHigh)
	runtime.KeepAlive(newLow)
	runtime.KeepAlive(aboveMa)
	runtime.KeepAlive(onBuySignal)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AbsoluteBreadthIndex) Reset() {
	C.wickra_absolute_breadth_index_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AbsoluteBreadthIndex) Close() {
	if ind.handle != nil {
		C.wickra_absolute_breadth_index_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AccelerationBands wraps the AccelerationBands indicator over the Wickra C ABI.
type AccelerationBands struct {
	handle *C.struct_AccelerationBands
}

// NewAccelerationBands constructs a AccelerationBands. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAccelerationBands(period int, factor float64) (*AccelerationBands, error) {
	ptr := C.wickra_acceleration_bands_new(C.uintptr_t(period), C.double(factor))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AccelerationBands{handle: ptr}
	runtime.SetFinalizer(obj, (*AccelerationBands).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AccelerationBands) WarmupPeriod() int {
	r := int(C.wickra_acceleration_bands_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AccelerationBands) IsReady() bool {
	r := bool(C.wickra_acceleration_bands_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AccelerationBands) Name() string {
	r := C.GoString(C.wickra_acceleration_bands_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *AccelerationBands) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (AccelerationBandsOutput, bool) {
	var out C.struct_WickraAccelerationBandsOutput
	ok := bool(C.wickra_acceleration_bands_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return AccelerationBandsOutput{}, false
	}
	return AccelerationBandsOutput{float64(out.upper), float64(out.middle), float64(out.lower)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AccelerationBands) Reset() {
	C.wickra_acceleration_bands_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AccelerationBands) Close() {
	if ind.handle != nil {
		C.wickra_acceleration_bands_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AcceleratorOscillator wraps the AcceleratorOscillator indicator over the Wickra C ABI.
type AcceleratorOscillator struct {
	handle *C.struct_AcceleratorOscillator
}

// NewAcceleratorOscillator constructs a AcceleratorOscillator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAcceleratorOscillator(aoFast int, aoSlow int, signalPeriod int) (*AcceleratorOscillator, error) {
	ptr := C.wickra_accelerator_oscillator_new(C.uintptr_t(aoFast), C.uintptr_t(aoSlow), C.uintptr_t(signalPeriod))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AcceleratorOscillator{handle: ptr}
	runtime.SetFinalizer(obj, (*AcceleratorOscillator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AcceleratorOscillator) WarmupPeriod() int {
	r := int(C.wickra_accelerator_oscillator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AcceleratorOscillator) IsReady() bool {
	r := bool(C.wickra_accelerator_oscillator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AcceleratorOscillator) Name() string {
	r := C.GoString(C.wickra_accelerator_oscillator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *AcceleratorOscillator) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_accelerator_oscillator_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *AcceleratorOscillator) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_accelerator_oscillator_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AcceleratorOscillator) Reset() {
	C.wickra_accelerator_oscillator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AcceleratorOscillator) Close() {
	if ind.handle != nil {
		C.wickra_accelerator_oscillator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AdOscillator wraps the AdOscillator indicator over the Wickra C ABI.
type AdOscillator struct {
	handle *C.struct_AdOscillator
}

// NewAdOscillator constructs a AdOscillator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAdOscillator() (*AdOscillator, error) {
	ptr := C.wickra_ad_oscillator_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AdOscillator{handle: ptr}
	runtime.SetFinalizer(obj, (*AdOscillator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AdOscillator) WarmupPeriod() int {
	r := int(C.wickra_ad_oscillator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AdOscillator) IsReady() bool {
	r := bool(C.wickra_ad_oscillator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AdOscillator) Name() string {
	r := C.GoString(C.wickra_ad_oscillator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *AdOscillator) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_ad_oscillator_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *AdOscillator) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_ad_oscillator_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AdOscillator) Reset() {
	C.wickra_ad_oscillator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AdOscillator) Close() {
	if ind.handle != nil {
		C.wickra_ad_oscillator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AdVolumeLine wraps the AdVolumeLine indicator over the Wickra C ABI.
type AdVolumeLine struct {
	handle *C.struct_AdVolumeLine
}

// NewAdVolumeLine constructs a AdVolumeLine. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAdVolumeLine() (*AdVolumeLine, error) {
	ptr := C.wickra_ad_volume_line_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AdVolumeLine{handle: ptr}
	runtime.SetFinalizer(obj, (*AdVolumeLine).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AdVolumeLine) WarmupPeriod() int {
	r := int(C.wickra_ad_volume_line_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AdVolumeLine) IsReady() bool {
	r := bool(C.wickra_ad_volume_line_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AdVolumeLine) Name() string {
	r := C.GoString(C.wickra_ad_volume_line_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *AdVolumeLine) Update(change []float64, volume []float64, newHigh []bool, newLow []bool, aboveMa []bool, onBuySignal []bool, timestamp int64) float64 {
	if len(volume) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newHigh) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newLow) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(aboveMa) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(onBuySignal) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_ad_volume_line_update(ind.handle, (*C.double)(unsafe.Pointer(&change[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.bool)(unsafe.Pointer(&newHigh[0])), (*C.bool)(unsafe.Pointer(&newLow[0])), (*C.bool)(unsafe.Pointer(&aboveMa[0])), (*C.bool)(unsafe.Pointer(&onBuySignal[0])), C.uintptr_t(len(change)), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(change)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(newHigh)
	runtime.KeepAlive(newLow)
	runtime.KeepAlive(aboveMa)
	runtime.KeepAlive(onBuySignal)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AdVolumeLine) Reset() {
	C.wickra_ad_volume_line_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AdVolumeLine) Close() {
	if ind.handle != nil {
		C.wickra_ad_volume_line_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AdaptiveCci wraps the AdaptiveCci indicator over the Wickra C ABI.
type AdaptiveCci struct {
	handle *C.struct_AdaptiveCci
}

// NewAdaptiveCci constructs a AdaptiveCci. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAdaptiveCci(period int) (*AdaptiveCci, error) {
	ptr := C.wickra_adaptive_cci_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AdaptiveCci{handle: ptr}
	runtime.SetFinalizer(obj, (*AdaptiveCci).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AdaptiveCci) WarmupPeriod() int {
	r := int(C.wickra_adaptive_cci_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AdaptiveCci) IsReady() bool {
	r := bool(C.wickra_adaptive_cci_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AdaptiveCci) Name() string {
	r := C.GoString(C.wickra_adaptive_cci_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *AdaptiveCci) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_adaptive_cci_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *AdaptiveCci) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_adaptive_cci_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AdaptiveCci) Reset() {
	C.wickra_adaptive_cci_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AdaptiveCci) Close() {
	if ind.handle != nil {
		C.wickra_adaptive_cci_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AdaptiveCycle wraps the AdaptiveCycle indicator over the Wickra C ABI.
type AdaptiveCycle struct {
	handle *C.struct_AdaptiveCycle
}

// NewAdaptiveCycle constructs a AdaptiveCycle. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAdaptiveCycle() (*AdaptiveCycle, error) {
	ptr := C.wickra_adaptive_cycle_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AdaptiveCycle{handle: ptr}
	runtime.SetFinalizer(obj, (*AdaptiveCycle).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AdaptiveCycle) WarmupPeriod() int {
	r := int(C.wickra_adaptive_cycle_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AdaptiveCycle) IsReady() bool {
	r := bool(C.wickra_adaptive_cycle_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AdaptiveCycle) Name() string {
	r := C.GoString(C.wickra_adaptive_cycle_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *AdaptiveCycle) Update(value float64) float64 {
	r := float64(C.wickra_adaptive_cycle_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *AdaptiveCycle) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_adaptive_cycle_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AdaptiveCycle) Reset() {
	C.wickra_adaptive_cycle_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AdaptiveCycle) Close() {
	if ind.handle != nil {
		C.wickra_adaptive_cycle_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AdaptiveLaguerreFilter wraps the AdaptiveLaguerreFilter indicator over the Wickra C ABI.
type AdaptiveLaguerreFilter struct {
	handle *C.struct_AdaptiveLaguerreFilter
}

// NewAdaptiveLaguerreFilter constructs a AdaptiveLaguerreFilter. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAdaptiveLaguerreFilter(period int) (*AdaptiveLaguerreFilter, error) {
	ptr := C.wickra_adaptive_laguerre_filter_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AdaptiveLaguerreFilter{handle: ptr}
	runtime.SetFinalizer(obj, (*AdaptiveLaguerreFilter).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AdaptiveLaguerreFilter) WarmupPeriod() int {
	r := int(C.wickra_adaptive_laguerre_filter_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AdaptiveLaguerreFilter) IsReady() bool {
	r := bool(C.wickra_adaptive_laguerre_filter_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AdaptiveLaguerreFilter) Name() string {
	r := C.GoString(C.wickra_adaptive_laguerre_filter_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *AdaptiveLaguerreFilter) Update(value float64) float64 {
	r := float64(C.wickra_adaptive_laguerre_filter_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *AdaptiveLaguerreFilter) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_adaptive_laguerre_filter_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AdaptiveLaguerreFilter) Reset() {
	C.wickra_adaptive_laguerre_filter_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AdaptiveLaguerreFilter) Close() {
	if ind.handle != nil {
		C.wickra_adaptive_laguerre_filter_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AdaptiveRsi wraps the AdaptiveRsi indicator over the Wickra C ABI.
type AdaptiveRsi struct {
	handle *C.struct_AdaptiveRsi
}

// NewAdaptiveRsi constructs a AdaptiveRsi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAdaptiveRsi(period int) (*AdaptiveRsi, error) {
	ptr := C.wickra_adaptive_rsi_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AdaptiveRsi{handle: ptr}
	runtime.SetFinalizer(obj, (*AdaptiveRsi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AdaptiveRsi) WarmupPeriod() int {
	r := int(C.wickra_adaptive_rsi_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AdaptiveRsi) IsReady() bool {
	r := bool(C.wickra_adaptive_rsi_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AdaptiveRsi) Name() string {
	r := C.GoString(C.wickra_adaptive_rsi_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *AdaptiveRsi) Update(value float64) float64 {
	r := float64(C.wickra_adaptive_rsi_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *AdaptiveRsi) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_adaptive_rsi_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AdaptiveRsi) Reset() {
	C.wickra_adaptive_rsi_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AdaptiveRsi) Close() {
	if ind.handle != nil {
		C.wickra_adaptive_rsi_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Adl wraps the Adl indicator over the Wickra C ABI.
type Adl struct {
	handle *C.struct_Adl
}

// NewAdl constructs a Adl. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAdl() (*Adl, error) {
	ptr := C.wickra_adl_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Adl{handle: ptr}
	runtime.SetFinalizer(obj, (*Adl).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Adl) WarmupPeriod() int {
	r := int(C.wickra_adl_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Adl) IsReady() bool {
	r := bool(C.wickra_adl_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Adl) Name() string {
	r := C.GoString(C.wickra_adl_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Adl) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_adl_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Adl) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_adl_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Adl) Reset() {
	C.wickra_adl_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Adl) Close() {
	if ind.handle != nil {
		C.wickra_adl_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AdvanceBlock wraps the AdvanceBlock indicator over the Wickra C ABI.
type AdvanceBlock struct {
	handle *C.struct_AdvanceBlock
}

// NewAdvanceBlock constructs a AdvanceBlock. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAdvanceBlock() (*AdvanceBlock, error) {
	ptr := C.wickra_advance_block_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AdvanceBlock{handle: ptr}
	runtime.SetFinalizer(obj, (*AdvanceBlock).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AdvanceBlock) WarmupPeriod() int {
	r := int(C.wickra_advance_block_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AdvanceBlock) IsReady() bool {
	r := bool(C.wickra_advance_block_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AdvanceBlock) Name() string {
	r := C.GoString(C.wickra_advance_block_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *AdvanceBlock) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_advance_block_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *AdvanceBlock) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_advance_block_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AdvanceBlock) Reset() {
	C.wickra_advance_block_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AdvanceBlock) Close() {
	if ind.handle != nil {
		C.wickra_advance_block_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AdvanceDecline wraps the AdvanceDecline indicator over the Wickra C ABI.
type AdvanceDecline struct {
	handle *C.struct_AdvanceDecline
}

// NewAdvanceDecline constructs a AdvanceDecline. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAdvanceDecline() (*AdvanceDecline, error) {
	ptr := C.wickra_advance_decline_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AdvanceDecline{handle: ptr}
	runtime.SetFinalizer(obj, (*AdvanceDecline).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AdvanceDecline) WarmupPeriod() int {
	r := int(C.wickra_advance_decline_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AdvanceDecline) IsReady() bool {
	r := bool(C.wickra_advance_decline_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AdvanceDecline) Name() string {
	r := C.GoString(C.wickra_advance_decline_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *AdvanceDecline) Update(change []float64, volume []float64, newHigh []bool, newLow []bool, aboveMa []bool, onBuySignal []bool, timestamp int64) float64 {
	if len(volume) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newHigh) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newLow) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(aboveMa) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(onBuySignal) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_advance_decline_update(ind.handle, (*C.double)(unsafe.Pointer(&change[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.bool)(unsafe.Pointer(&newHigh[0])), (*C.bool)(unsafe.Pointer(&newLow[0])), (*C.bool)(unsafe.Pointer(&aboveMa[0])), (*C.bool)(unsafe.Pointer(&onBuySignal[0])), C.uintptr_t(len(change)), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(change)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(newHigh)
	runtime.KeepAlive(newLow)
	runtime.KeepAlive(aboveMa)
	runtime.KeepAlive(onBuySignal)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AdvanceDecline) Reset() {
	C.wickra_advance_decline_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AdvanceDecline) Close() {
	if ind.handle != nil {
		C.wickra_advance_decline_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AdvanceDeclineRatio wraps the AdvanceDeclineRatio indicator over the Wickra C ABI.
type AdvanceDeclineRatio struct {
	handle *C.struct_AdvanceDeclineRatio
}

// NewAdvanceDeclineRatio constructs a AdvanceDeclineRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAdvanceDeclineRatio() (*AdvanceDeclineRatio, error) {
	ptr := C.wickra_advance_decline_ratio_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AdvanceDeclineRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*AdvanceDeclineRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AdvanceDeclineRatio) WarmupPeriod() int {
	r := int(C.wickra_advance_decline_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AdvanceDeclineRatio) IsReady() bool {
	r := bool(C.wickra_advance_decline_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AdvanceDeclineRatio) Name() string {
	r := C.GoString(C.wickra_advance_decline_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *AdvanceDeclineRatio) Update(change []float64, volume []float64, newHigh []bool, newLow []bool, aboveMa []bool, onBuySignal []bool, timestamp int64) float64 {
	if len(volume) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newHigh) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newLow) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(aboveMa) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(onBuySignal) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_advance_decline_ratio_update(ind.handle, (*C.double)(unsafe.Pointer(&change[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.bool)(unsafe.Pointer(&newHigh[0])), (*C.bool)(unsafe.Pointer(&newLow[0])), (*C.bool)(unsafe.Pointer(&aboveMa[0])), (*C.bool)(unsafe.Pointer(&onBuySignal[0])), C.uintptr_t(len(change)), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(change)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(newHigh)
	runtime.KeepAlive(newLow)
	runtime.KeepAlive(aboveMa)
	runtime.KeepAlive(onBuySignal)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AdvanceDeclineRatio) Reset() {
	C.wickra_advance_decline_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AdvanceDeclineRatio) Close() {
	if ind.handle != nil {
		C.wickra_advance_decline_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Adx wraps the Adx indicator over the Wickra C ABI.
type Adx struct {
	handle *C.struct_Adx
}

// NewAdx constructs a Adx. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAdx(period int) (*Adx, error) {
	ptr := C.wickra_adx_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Adx{handle: ptr}
	runtime.SetFinalizer(obj, (*Adx).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Adx) WarmupPeriod() int {
	r := int(C.wickra_adx_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Adx) IsReady() bool {
	r := bool(C.wickra_adx_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Adx) Name() string {
	r := C.GoString(C.wickra_adx_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *Adx) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (AdxOutput, bool) {
	var out C.struct_WickraAdxOutput
	ok := bool(C.wickra_adx_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return AdxOutput{}, false
	}
	return AdxOutput{float64(out.plus_di), float64(out.minus_di), float64(out.adx)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Adx) Reset() {
	C.wickra_adx_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Adx) Close() {
	if ind.handle != nil {
		C.wickra_adx_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Adxr wraps the Adxr indicator over the Wickra C ABI.
type Adxr struct {
	handle *C.struct_Adxr
}

// NewAdxr constructs a Adxr. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAdxr(period int) (*Adxr, error) {
	ptr := C.wickra_adxr_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Adxr{handle: ptr}
	runtime.SetFinalizer(obj, (*Adxr).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Adxr) WarmupPeriod() int {
	r := int(C.wickra_adxr_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Adxr) IsReady() bool {
	r := bool(C.wickra_adxr_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Adxr) Name() string {
	r := C.GoString(C.wickra_adxr_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Adxr) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_adxr_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Adxr) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_adxr_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Adxr) Reset() {
	C.wickra_adxr_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Adxr) Close() {
	if ind.handle != nil {
		C.wickra_adxr_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Alligator wraps the Alligator indicator over the Wickra C ABI.
type Alligator struct {
	handle *C.struct_Alligator
}

// NewAlligator constructs a Alligator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAlligator(jawPeriod int, teethPeriod int, lipsPeriod int) (*Alligator, error) {
	ptr := C.wickra_alligator_new(C.uintptr_t(jawPeriod), C.uintptr_t(teethPeriod), C.uintptr_t(lipsPeriod))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Alligator{handle: ptr}
	runtime.SetFinalizer(obj, (*Alligator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Alligator) WarmupPeriod() int {
	r := int(C.wickra_alligator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Alligator) IsReady() bool {
	r := bool(C.wickra_alligator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Alligator) Name() string {
	r := C.GoString(C.wickra_alligator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *Alligator) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (AlligatorOutput, bool) {
	var out C.struct_WickraAlligatorOutput
	ok := bool(C.wickra_alligator_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return AlligatorOutput{}, false
	}
	return AlligatorOutput{float64(out.jaw), float64(out.teeth), float64(out.lips)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Alligator) Reset() {
	C.wickra_alligator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Alligator) Close() {
	if ind.handle != nil {
		C.wickra_alligator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Alma wraps the Alma indicator over the Wickra C ABI.
type Alma struct {
	handle *C.struct_Alma
}

// NewAlma constructs a Alma. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAlma(period int, offset float64, sigma float64) (*Alma, error) {
	ptr := C.wickra_alma_new(C.uintptr_t(period), C.double(offset), C.double(sigma))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Alma{handle: ptr}
	runtime.SetFinalizer(obj, (*Alma).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Alma) WarmupPeriod() int {
	r := int(C.wickra_alma_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Alma) IsReady() bool {
	r := bool(C.wickra_alma_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Alma) Name() string {
	r := C.GoString(C.wickra_alma_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Alma) Update(value float64) float64 {
	r := float64(C.wickra_alma_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Alma) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_alma_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Alma) Reset() {
	C.wickra_alma_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Alma) Close() {
	if ind.handle != nil {
		C.wickra_alma_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Alpha wraps the Alpha indicator over the Wickra C ABI.
type Alpha struct {
	handle *C.struct_Alpha
}

// NewAlpha constructs a Alpha. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAlpha(period int, riskFree float64) (*Alpha, error) {
	ptr := C.wickra_alpha_new(C.uintptr_t(period), C.double(riskFree))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Alpha{handle: ptr}
	runtime.SetFinalizer(obj, (*Alpha).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Alpha) WarmupPeriod() int {
	r := int(C.wickra_alpha_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Alpha) IsReady() bool {
	r := bool(C.wickra_alpha_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Alpha) Name() string {
	r := C.GoString(C.wickra_alpha_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Alpha) Update(x float64, y float64) float64 {
	r := float64(C.wickra_alpha_update(ind.handle, C.double(x), C.double(y)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Alpha) Batch(x []float64, y []float64) []float64 {
	n := len(x)
	if len(y) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_alpha_batch(ind.handle, (*C.double)(unsafe.Pointer(&x[0])), (*C.double)(unsafe.Pointer(&y[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(x)
	runtime.KeepAlive(y)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Alpha) Reset() {
	C.wickra_alpha_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Alpha) Close() {
	if ind.handle != nil {
		C.wickra_alpha_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AmihudIlliquidity wraps the AmihudIlliquidity indicator over the Wickra C ABI.
type AmihudIlliquidity struct {
	handle *C.struct_AmihudIlliquidity
}

// NewAmihudIlliquidity constructs a AmihudIlliquidity. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAmihudIlliquidity(period int) (*AmihudIlliquidity, error) {
	ptr := C.wickra_amihud_illiquidity_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AmihudIlliquidity{handle: ptr}
	runtime.SetFinalizer(obj, (*AmihudIlliquidity).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AmihudIlliquidity) WarmupPeriod() int {
	r := int(C.wickra_amihud_illiquidity_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AmihudIlliquidity) IsReady() bool {
	r := bool(C.wickra_amihud_illiquidity_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AmihudIlliquidity) Name() string {
	r := C.GoString(C.wickra_amihud_illiquidity_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *AmihudIlliquidity) Update(price float64, size float64, isBuy bool, timestamp int64) float64 {
	r := float64(C.wickra_amihud_illiquidity_update(ind.handle, C.double(price), C.double(size), C.bool(isBuy), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AmihudIlliquidity) Reset() {
	C.wickra_amihud_illiquidity_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AmihudIlliquidity) Close() {
	if ind.handle != nil {
		C.wickra_amihud_illiquidity_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AnchoredRsi wraps the AnchoredRsi indicator over the Wickra C ABI.
type AnchoredRsi struct {
	handle *C.struct_AnchoredRsi
}

// NewAnchoredRsi constructs a AnchoredRsi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAnchoredRsi() (*AnchoredRsi, error) {
	ptr := C.wickra_anchored_rsi_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AnchoredRsi{handle: ptr}
	runtime.SetFinalizer(obj, (*AnchoredRsi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AnchoredRsi) WarmupPeriod() int {
	r := int(C.wickra_anchored_rsi_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AnchoredRsi) IsReady() bool {
	r := bool(C.wickra_anchored_rsi_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AnchoredRsi) Name() string {
	r := C.GoString(C.wickra_anchored_rsi_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *AnchoredRsi) Update(value float64) float64 {
	r := float64(C.wickra_anchored_rsi_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *AnchoredRsi) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_anchored_rsi_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AnchoredRsi) Reset() {
	C.wickra_anchored_rsi_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AnchoredRsi) Close() {
	if ind.handle != nil {
		C.wickra_anchored_rsi_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AnchoredVwap wraps the AnchoredVwap indicator over the Wickra C ABI.
type AnchoredVwap struct {
	handle *C.struct_AnchoredVwap
}

// NewAnchoredVwap constructs a AnchoredVwap. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAnchoredVwap() (*AnchoredVwap, error) {
	ptr := C.wickra_anchored_vwap_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AnchoredVwap{handle: ptr}
	runtime.SetFinalizer(obj, (*AnchoredVwap).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AnchoredVwap) WarmupPeriod() int {
	r := int(C.wickra_anchored_vwap_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AnchoredVwap) IsReady() bool {
	r := bool(C.wickra_anchored_vwap_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AnchoredVwap) Name() string {
	r := C.GoString(C.wickra_anchored_vwap_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *AnchoredVwap) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_anchored_vwap_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *AnchoredVwap) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_anchored_vwap_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AnchoredVwap) Reset() {
	C.wickra_anchored_vwap_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AnchoredVwap) Close() {
	if ind.handle != nil {
		C.wickra_anchored_vwap_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AndrewsPitchfork wraps the AndrewsPitchfork indicator over the Wickra C ABI.
type AndrewsPitchfork struct {
	handle *C.struct_AndrewsPitchfork
}

// NewAndrewsPitchfork constructs a AndrewsPitchfork. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAndrewsPitchfork(strength int) (*AndrewsPitchfork, error) {
	ptr := C.wickra_andrews_pitchfork_new(C.uintptr_t(strength))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AndrewsPitchfork{handle: ptr}
	runtime.SetFinalizer(obj, (*AndrewsPitchfork).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AndrewsPitchfork) WarmupPeriod() int {
	r := int(C.wickra_andrews_pitchfork_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AndrewsPitchfork) IsReady() bool {
	r := bool(C.wickra_andrews_pitchfork_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AndrewsPitchfork) Name() string {
	r := C.GoString(C.wickra_andrews_pitchfork_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *AndrewsPitchfork) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (AndrewsPitchforkOutput, bool) {
	var out C.struct_WickraAndrewsPitchforkOutput
	ok := bool(C.wickra_andrews_pitchfork_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return AndrewsPitchforkOutput{}, false
	}
	return AndrewsPitchforkOutput{float64(out.median), float64(out.upper), float64(out.lower)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AndrewsPitchfork) Reset() {
	C.wickra_andrews_pitchfork_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AndrewsPitchfork) Close() {
	if ind.handle != nil {
		C.wickra_andrews_pitchfork_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Apo wraps the Apo indicator over the Wickra C ABI.
type Apo struct {
	handle *C.struct_Apo
}

// NewApo constructs a Apo. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewApo(fast int, slow int) (*Apo, error) {
	ptr := C.wickra_apo_new(C.uintptr_t(fast), C.uintptr_t(slow))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Apo{handle: ptr}
	runtime.SetFinalizer(obj, (*Apo).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Apo) WarmupPeriod() int {
	r := int(C.wickra_apo_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Apo) IsReady() bool {
	r := bool(C.wickra_apo_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Apo) Name() string {
	r := C.GoString(C.wickra_apo_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Apo) Update(value float64) float64 {
	r := float64(C.wickra_apo_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Apo) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_apo_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Apo) Reset() {
	C.wickra_apo_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Apo) Close() {
	if ind.handle != nil {
		C.wickra_apo_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Aroon wraps the Aroon indicator over the Wickra C ABI.
type Aroon struct {
	handle *C.struct_Aroon
}

// NewAroon constructs a Aroon. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAroon(period int) (*Aroon, error) {
	ptr := C.wickra_aroon_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Aroon{handle: ptr}
	runtime.SetFinalizer(obj, (*Aroon).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Aroon) WarmupPeriod() int {
	r := int(C.wickra_aroon_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Aroon) IsReady() bool {
	r := bool(C.wickra_aroon_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Aroon) Name() string {
	r := C.GoString(C.wickra_aroon_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *Aroon) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (AroonOutput, bool) {
	var out C.struct_WickraAroonOutput
	ok := bool(C.wickra_aroon_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return AroonOutput{}, false
	}
	return AroonOutput{float64(out.up), float64(out.down)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Aroon) Reset() {
	C.wickra_aroon_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Aroon) Close() {
	if ind.handle != nil {
		C.wickra_aroon_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AroonOscillator wraps the AroonOscillator indicator over the Wickra C ABI.
type AroonOscillator struct {
	handle *C.struct_AroonOscillator
}

// NewAroonOscillator constructs a AroonOscillator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAroonOscillator(period int) (*AroonOscillator, error) {
	ptr := C.wickra_aroon_oscillator_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AroonOscillator{handle: ptr}
	runtime.SetFinalizer(obj, (*AroonOscillator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AroonOscillator) WarmupPeriod() int {
	r := int(C.wickra_aroon_oscillator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AroonOscillator) IsReady() bool {
	r := bool(C.wickra_aroon_oscillator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AroonOscillator) Name() string {
	r := C.GoString(C.wickra_aroon_oscillator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *AroonOscillator) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_aroon_oscillator_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *AroonOscillator) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_aroon_oscillator_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AroonOscillator) Reset() {
	C.wickra_aroon_oscillator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AroonOscillator) Close() {
	if ind.handle != nil {
		C.wickra_aroon_oscillator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Atr wraps the Atr indicator over the Wickra C ABI.
type Atr struct {
	handle *C.struct_Atr
}

// NewAtr constructs a Atr. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAtr(period int) (*Atr, error) {
	ptr := C.wickra_atr_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Atr{handle: ptr}
	runtime.SetFinalizer(obj, (*Atr).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Atr) WarmupPeriod() int {
	r := int(C.wickra_atr_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Atr) IsReady() bool {
	r := bool(C.wickra_atr_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Atr) Name() string {
	r := C.GoString(C.wickra_atr_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Atr) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_atr_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Atr) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_atr_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Atr) Reset() {
	C.wickra_atr_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Atr) Close() {
	if ind.handle != nil {
		C.wickra_atr_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AtrBands wraps the AtrBands indicator over the Wickra C ABI.
type AtrBands struct {
	handle *C.struct_AtrBands
}

// NewAtrBands constructs a AtrBands. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAtrBands(period int, multiplier float64) (*AtrBands, error) {
	ptr := C.wickra_atr_bands_new(C.uintptr_t(period), C.double(multiplier))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AtrBands{handle: ptr}
	runtime.SetFinalizer(obj, (*AtrBands).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AtrBands) WarmupPeriod() int {
	r := int(C.wickra_atr_bands_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AtrBands) IsReady() bool {
	r := bool(C.wickra_atr_bands_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AtrBands) Name() string {
	r := C.GoString(C.wickra_atr_bands_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *AtrBands) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (AtrBandsOutput, bool) {
	var out C.struct_WickraAtrBandsOutput
	ok := bool(C.wickra_atr_bands_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return AtrBandsOutput{}, false
	}
	return AtrBandsOutput{float64(out.upper), float64(out.middle), float64(out.lower)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AtrBands) Reset() {
	C.wickra_atr_bands_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AtrBands) Close() {
	if ind.handle != nil {
		C.wickra_atr_bands_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AtrRatchet wraps the AtrRatchet indicator over the Wickra C ABI.
type AtrRatchet struct {
	handle *C.struct_AtrRatchet
}

// NewAtrRatchet constructs a AtrRatchet. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAtrRatchet(atrPeriod int, startMult float64, increment float64) (*AtrRatchet, error) {
	ptr := C.wickra_atr_ratchet_new(C.uintptr_t(atrPeriod), C.double(startMult), C.double(increment))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AtrRatchet{handle: ptr}
	runtime.SetFinalizer(obj, (*AtrRatchet).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AtrRatchet) WarmupPeriod() int {
	r := int(C.wickra_atr_ratchet_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AtrRatchet) IsReady() bool {
	r := bool(C.wickra_atr_ratchet_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AtrRatchet) Name() string {
	r := C.GoString(C.wickra_atr_ratchet_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *AtrRatchet) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (AtrRatchetOutput, bool) {
	var out C.struct_WickraAtrRatchetOutput
	ok := bool(C.wickra_atr_ratchet_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return AtrRatchetOutput{}, false
	}
	return AtrRatchetOutput{float64(out.value), float64(out.direction)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AtrRatchet) Reset() {
	C.wickra_atr_ratchet_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AtrRatchet) Close() {
	if ind.handle != nil {
		C.wickra_atr_ratchet_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AtrTrailingStop wraps the AtrTrailingStop indicator over the Wickra C ABI.
type AtrTrailingStop struct {
	handle *C.struct_AtrTrailingStop
}

// NewAtrTrailingStop constructs a AtrTrailingStop. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAtrTrailingStop(atrPeriod int, multiplier float64) (*AtrTrailingStop, error) {
	ptr := C.wickra_atr_trailing_stop_new(C.uintptr_t(atrPeriod), C.double(multiplier))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AtrTrailingStop{handle: ptr}
	runtime.SetFinalizer(obj, (*AtrTrailingStop).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AtrTrailingStop) WarmupPeriod() int {
	r := int(C.wickra_atr_trailing_stop_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AtrTrailingStop) IsReady() bool {
	r := bool(C.wickra_atr_trailing_stop_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AtrTrailingStop) Name() string {
	r := C.GoString(C.wickra_atr_trailing_stop_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *AtrTrailingStop) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_atr_trailing_stop_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *AtrTrailingStop) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_atr_trailing_stop_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AtrTrailingStop) Reset() {
	C.wickra_atr_trailing_stop_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AtrTrailingStop) Close() {
	if ind.handle != nil {
		C.wickra_atr_trailing_stop_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AutoFib wraps the AutoFib indicator over the Wickra C ABI.
type AutoFib struct {
	handle *C.struct_AutoFib
}

// NewAutoFib constructs a AutoFib. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAutoFib() (*AutoFib, error) {
	ptr := C.wickra_auto_fib_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AutoFib{handle: ptr}
	runtime.SetFinalizer(obj, (*AutoFib).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AutoFib) WarmupPeriod() int {
	r := int(C.wickra_auto_fib_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AutoFib) IsReady() bool {
	r := bool(C.wickra_auto_fib_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AutoFib) Name() string {
	r := C.GoString(C.wickra_auto_fib_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *AutoFib) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (AutoFibOutput, bool) {
	var out C.struct_WickraAutoFibOutput
	ok := bool(C.wickra_auto_fib_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return AutoFibOutput{}, false
	}
	return AutoFibOutput{float64(out.level_0), float64(out.level_236), float64(out.level_382), float64(out.level_500), float64(out.level_618), float64(out.level_786), float64(out.level_1000)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AutoFib) Reset() {
	C.wickra_auto_fib_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AutoFib) Close() {
	if ind.handle != nil {
		C.wickra_auto_fib_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Autocorrelation wraps the Autocorrelation indicator over the Wickra C ABI.
type Autocorrelation struct {
	handle *C.struct_Autocorrelation
}

// NewAutocorrelation constructs a Autocorrelation. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAutocorrelation(period int, lag int) (*Autocorrelation, error) {
	ptr := C.wickra_autocorrelation_new(C.uintptr_t(period), C.uintptr_t(lag))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Autocorrelation{handle: ptr}
	runtime.SetFinalizer(obj, (*Autocorrelation).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Autocorrelation) WarmupPeriod() int {
	r := int(C.wickra_autocorrelation_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Autocorrelation) IsReady() bool {
	r := bool(C.wickra_autocorrelation_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Autocorrelation) Name() string {
	r := C.GoString(C.wickra_autocorrelation_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Autocorrelation) Update(value float64) float64 {
	r := float64(C.wickra_autocorrelation_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Autocorrelation) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_autocorrelation_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Autocorrelation) Reset() {
	C.wickra_autocorrelation_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Autocorrelation) Close() {
	if ind.handle != nil {
		C.wickra_autocorrelation_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AutocorrelationPeriodogram wraps the AutocorrelationPeriodogram indicator over the Wickra C ABI.
type AutocorrelationPeriodogram struct {
	handle *C.struct_AutocorrelationPeriodogram
}

// NewAutocorrelationPeriodogram constructs a AutocorrelationPeriodogram. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAutocorrelationPeriodogram(minPeriod int, maxPeriod int) (*AutocorrelationPeriodogram, error) {
	ptr := C.wickra_autocorrelation_periodogram_new(C.uintptr_t(minPeriod), C.uintptr_t(maxPeriod))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AutocorrelationPeriodogram{handle: ptr}
	runtime.SetFinalizer(obj, (*AutocorrelationPeriodogram).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AutocorrelationPeriodogram) WarmupPeriod() int {
	r := int(C.wickra_autocorrelation_periodogram_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AutocorrelationPeriodogram) IsReady() bool {
	r := bool(C.wickra_autocorrelation_periodogram_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AutocorrelationPeriodogram) Name() string {
	r := C.GoString(C.wickra_autocorrelation_periodogram_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *AutocorrelationPeriodogram) Update(value float64) float64 {
	r := float64(C.wickra_autocorrelation_periodogram_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *AutocorrelationPeriodogram) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_autocorrelation_periodogram_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AutocorrelationPeriodogram) Reset() {
	C.wickra_autocorrelation_periodogram_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AutocorrelationPeriodogram) Close() {
	if ind.handle != nil {
		C.wickra_autocorrelation_periodogram_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AverageDailyRange wraps the AverageDailyRange indicator over the Wickra C ABI.
type AverageDailyRange struct {
	handle *C.struct_AverageDailyRange
}

// NewAverageDailyRange constructs a AverageDailyRange. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAverageDailyRange(period int, utcOffsetMinutes int32) (*AverageDailyRange, error) {
	ptr := C.wickra_average_daily_range_new(C.uintptr_t(period), C.int32_t(utcOffsetMinutes))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AverageDailyRange{handle: ptr}
	runtime.SetFinalizer(obj, (*AverageDailyRange).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AverageDailyRange) WarmupPeriod() int {
	r := int(C.wickra_average_daily_range_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AverageDailyRange) IsReady() bool {
	r := bool(C.wickra_average_daily_range_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AverageDailyRange) Name() string {
	r := C.GoString(C.wickra_average_daily_range_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *AverageDailyRange) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_average_daily_range_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *AverageDailyRange) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_average_daily_range_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AverageDailyRange) Reset() {
	C.wickra_average_daily_range_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AverageDailyRange) Close() {
	if ind.handle != nil {
		C.wickra_average_daily_range_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AverageDrawdown wraps the AverageDrawdown indicator over the Wickra C ABI.
type AverageDrawdown struct {
	handle *C.struct_AverageDrawdown
}

// NewAverageDrawdown constructs a AverageDrawdown. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAverageDrawdown(period int) (*AverageDrawdown, error) {
	ptr := C.wickra_average_drawdown_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AverageDrawdown{handle: ptr}
	runtime.SetFinalizer(obj, (*AverageDrawdown).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AverageDrawdown) WarmupPeriod() int {
	r := int(C.wickra_average_drawdown_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AverageDrawdown) IsReady() bool {
	r := bool(C.wickra_average_drawdown_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AverageDrawdown) Name() string {
	r := C.GoString(C.wickra_average_drawdown_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *AverageDrawdown) Update(value float64) float64 {
	r := float64(C.wickra_average_drawdown_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *AverageDrawdown) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_average_drawdown_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AverageDrawdown) Reset() {
	C.wickra_average_drawdown_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AverageDrawdown) Close() {
	if ind.handle != nil {
		C.wickra_average_drawdown_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AvgPrice wraps the AvgPrice indicator over the Wickra C ABI.
type AvgPrice struct {
	handle *C.struct_AvgPrice
}

// NewAvgPrice constructs a AvgPrice. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAvgPrice() (*AvgPrice, error) {
	ptr := C.wickra_avg_price_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AvgPrice{handle: ptr}
	runtime.SetFinalizer(obj, (*AvgPrice).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AvgPrice) WarmupPeriod() int {
	r := int(C.wickra_avg_price_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AvgPrice) IsReady() bool {
	r := bool(C.wickra_avg_price_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AvgPrice) Name() string {
	r := C.GoString(C.wickra_avg_price_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *AvgPrice) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_avg_price_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *AvgPrice) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_avg_price_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AvgPrice) Reset() {
	C.wickra_avg_price_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AvgPrice) Close() {
	if ind.handle != nil {
		C.wickra_avg_price_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AwesomeOscillator wraps the AwesomeOscillator indicator over the Wickra C ABI.
type AwesomeOscillator struct {
	handle *C.struct_AwesomeOscillator
}

// NewAwesomeOscillator constructs a AwesomeOscillator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAwesomeOscillator(fast int, slow int) (*AwesomeOscillator, error) {
	ptr := C.wickra_awesome_oscillator_new(C.uintptr_t(fast), C.uintptr_t(slow))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AwesomeOscillator{handle: ptr}
	runtime.SetFinalizer(obj, (*AwesomeOscillator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AwesomeOscillator) WarmupPeriod() int {
	r := int(C.wickra_awesome_oscillator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AwesomeOscillator) IsReady() bool {
	r := bool(C.wickra_awesome_oscillator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AwesomeOscillator) Name() string {
	r := C.GoString(C.wickra_awesome_oscillator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *AwesomeOscillator) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_awesome_oscillator_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *AwesomeOscillator) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_awesome_oscillator_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AwesomeOscillator) Reset() {
	C.wickra_awesome_oscillator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AwesomeOscillator) Close() {
	if ind.handle != nil {
		C.wickra_awesome_oscillator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// AwesomeOscillatorHistogram wraps the AwesomeOscillatorHistogram indicator over the Wickra C ABI.
type AwesomeOscillatorHistogram struct {
	handle *C.struct_AwesomeOscillatorHistogram
}

// NewAwesomeOscillatorHistogram constructs a AwesomeOscillatorHistogram. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewAwesomeOscillatorHistogram(fast int, slow int, lookback int) (*AwesomeOscillatorHistogram, error) {
	ptr := C.wickra_awesome_oscillator_histogram_new(C.uintptr_t(fast), C.uintptr_t(slow), C.uintptr_t(lookback))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &AwesomeOscillatorHistogram{handle: ptr}
	runtime.SetFinalizer(obj, (*AwesomeOscillatorHistogram).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *AwesomeOscillatorHistogram) WarmupPeriod() int {
	r := int(C.wickra_awesome_oscillator_histogram_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *AwesomeOscillatorHistogram) IsReady() bool {
	r := bool(C.wickra_awesome_oscillator_histogram_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *AwesomeOscillatorHistogram) Name() string {
	r := C.GoString(C.wickra_awesome_oscillator_histogram_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *AwesomeOscillatorHistogram) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_awesome_oscillator_histogram_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *AwesomeOscillatorHistogram) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_awesome_oscillator_histogram_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *AwesomeOscillatorHistogram) Reset() {
	C.wickra_awesome_oscillator_histogram_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *AwesomeOscillatorHistogram) Close() {
	if ind.handle != nil {
		C.wickra_awesome_oscillator_histogram_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// BalanceOfPower wraps the BalanceOfPower indicator over the Wickra C ABI.
type BalanceOfPower struct {
	handle *C.struct_BalanceOfPower
}

// NewBalanceOfPower constructs a BalanceOfPower. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewBalanceOfPower() (*BalanceOfPower, error) {
	ptr := C.wickra_balance_of_power_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &BalanceOfPower{handle: ptr}
	runtime.SetFinalizer(obj, (*BalanceOfPower).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *BalanceOfPower) WarmupPeriod() int {
	r := int(C.wickra_balance_of_power_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *BalanceOfPower) IsReady() bool {
	r := bool(C.wickra_balance_of_power_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *BalanceOfPower) Name() string {
	r := C.GoString(C.wickra_balance_of_power_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *BalanceOfPower) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_balance_of_power_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *BalanceOfPower) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_balance_of_power_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *BalanceOfPower) Reset() {
	C.wickra_balance_of_power_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *BalanceOfPower) Close() {
	if ind.handle != nil {
		C.wickra_balance_of_power_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// BandpassFilter wraps the BandpassFilter indicator over the Wickra C ABI.
type BandpassFilter struct {
	handle *C.struct_BandpassFilter
}

// NewBandpassFilter constructs a BandpassFilter. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewBandpassFilter(period int, bandwidth float64) (*BandpassFilter, error) {
	ptr := C.wickra_bandpass_filter_new(C.uintptr_t(period), C.double(bandwidth))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &BandpassFilter{handle: ptr}
	runtime.SetFinalizer(obj, (*BandpassFilter).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *BandpassFilter) WarmupPeriod() int {
	r := int(C.wickra_bandpass_filter_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *BandpassFilter) IsReady() bool {
	r := bool(C.wickra_bandpass_filter_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *BandpassFilter) Name() string {
	r := C.GoString(C.wickra_bandpass_filter_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *BandpassFilter) Update(value float64) float64 {
	r := float64(C.wickra_bandpass_filter_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *BandpassFilter) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_bandpass_filter_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *BandpassFilter) Reset() {
	C.wickra_bandpass_filter_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *BandpassFilter) Close() {
	if ind.handle != nil {
		C.wickra_bandpass_filter_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Bat wraps the Bat indicator over the Wickra C ABI.
type Bat struct {
	handle *C.struct_Bat
}

// NewBat constructs a Bat. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewBat() (*Bat, error) {
	ptr := C.wickra_bat_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Bat{handle: ptr}
	runtime.SetFinalizer(obj, (*Bat).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Bat) WarmupPeriod() int {
	r := int(C.wickra_bat_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Bat) IsReady() bool {
	r := bool(C.wickra_bat_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Bat) Name() string {
	r := C.GoString(C.wickra_bat_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Bat) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_bat_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Bat) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_bat_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Bat) Reset() {
	C.wickra_bat_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Bat) Close() {
	if ind.handle != nil {
		C.wickra_bat_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// BeltHold wraps the BeltHold indicator over the Wickra C ABI.
type BeltHold struct {
	handle *C.struct_BeltHold
}

// NewBeltHold constructs a BeltHold. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewBeltHold() (*BeltHold, error) {
	ptr := C.wickra_belt_hold_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &BeltHold{handle: ptr}
	runtime.SetFinalizer(obj, (*BeltHold).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *BeltHold) WarmupPeriod() int {
	r := int(C.wickra_belt_hold_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *BeltHold) IsReady() bool {
	r := bool(C.wickra_belt_hold_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *BeltHold) Name() string {
	r := C.GoString(C.wickra_belt_hold_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *BeltHold) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_belt_hold_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *BeltHold) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_belt_hold_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *BeltHold) Reset() {
	C.wickra_belt_hold_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *BeltHold) Close() {
	if ind.handle != nil {
		C.wickra_belt_hold_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Beta wraps the Beta indicator over the Wickra C ABI.
type Beta struct {
	handle *C.struct_Beta
}

// NewBeta constructs a Beta. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewBeta(period int) (*Beta, error) {
	ptr := C.wickra_beta_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Beta{handle: ptr}
	runtime.SetFinalizer(obj, (*Beta).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Beta) WarmupPeriod() int {
	r := int(C.wickra_beta_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Beta) IsReady() bool {
	r := bool(C.wickra_beta_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Beta) Name() string {
	r := C.GoString(C.wickra_beta_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Beta) Update(x float64, y float64) float64 {
	r := float64(C.wickra_beta_update(ind.handle, C.double(x), C.double(y)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Beta) Batch(x []float64, y []float64) []float64 {
	n := len(x)
	if len(y) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_beta_batch(ind.handle, (*C.double)(unsafe.Pointer(&x[0])), (*C.double)(unsafe.Pointer(&y[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(x)
	runtime.KeepAlive(y)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Beta) Reset() {
	C.wickra_beta_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Beta) Close() {
	if ind.handle != nil {
		C.wickra_beta_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// BetaNeutralSpread wraps the BetaNeutralSpread indicator over the Wickra C ABI.
type BetaNeutralSpread struct {
	handle *C.struct_BetaNeutralSpread
}

// NewBetaNeutralSpread constructs a BetaNeutralSpread. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewBetaNeutralSpread(period int) (*BetaNeutralSpread, error) {
	ptr := C.wickra_beta_neutral_spread_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &BetaNeutralSpread{handle: ptr}
	runtime.SetFinalizer(obj, (*BetaNeutralSpread).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *BetaNeutralSpread) WarmupPeriod() int {
	r := int(C.wickra_beta_neutral_spread_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *BetaNeutralSpread) IsReady() bool {
	r := bool(C.wickra_beta_neutral_spread_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *BetaNeutralSpread) Name() string {
	r := C.GoString(C.wickra_beta_neutral_spread_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *BetaNeutralSpread) Update(x float64, y float64) float64 {
	r := float64(C.wickra_beta_neutral_spread_update(ind.handle, C.double(x), C.double(y)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *BetaNeutralSpread) Batch(x []float64, y []float64) []float64 {
	n := len(x)
	if len(y) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_beta_neutral_spread_batch(ind.handle, (*C.double)(unsafe.Pointer(&x[0])), (*C.double)(unsafe.Pointer(&y[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(x)
	runtime.KeepAlive(y)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *BetaNeutralSpread) Reset() {
	C.wickra_beta_neutral_spread_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *BetaNeutralSpread) Close() {
	if ind.handle != nil {
		C.wickra_beta_neutral_spread_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// BetterVolume wraps the BetterVolume indicator over the Wickra C ABI.
type BetterVolume struct {
	handle *C.struct_BetterVolume
}

// NewBetterVolume constructs a BetterVolume. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewBetterVolume(period int) (*BetterVolume, error) {
	ptr := C.wickra_better_volume_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &BetterVolume{handle: ptr}
	runtime.SetFinalizer(obj, (*BetterVolume).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *BetterVolume) WarmupPeriod() int {
	r := int(C.wickra_better_volume_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *BetterVolume) IsReady() bool {
	r := bool(C.wickra_better_volume_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *BetterVolume) Name() string {
	r := C.GoString(C.wickra_better_volume_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *BetterVolume) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_better_volume_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *BetterVolume) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_better_volume_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *BetterVolume) Reset() {
	C.wickra_better_volume_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *BetterVolume) Close() {
	if ind.handle != nil {
		C.wickra_better_volume_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// BipowerVariation wraps the BipowerVariation indicator over the Wickra C ABI.
type BipowerVariation struct {
	handle *C.struct_BipowerVariation
}

// NewBipowerVariation constructs a BipowerVariation. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewBipowerVariation(period int) (*BipowerVariation, error) {
	ptr := C.wickra_bipower_variation_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &BipowerVariation{handle: ptr}
	runtime.SetFinalizer(obj, (*BipowerVariation).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *BipowerVariation) WarmupPeriod() int {
	r := int(C.wickra_bipower_variation_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *BipowerVariation) IsReady() bool {
	r := bool(C.wickra_bipower_variation_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *BipowerVariation) Name() string {
	r := C.GoString(C.wickra_bipower_variation_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *BipowerVariation) Update(value float64) float64 {
	r := float64(C.wickra_bipower_variation_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *BipowerVariation) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_bipower_variation_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *BipowerVariation) Reset() {
	C.wickra_bipower_variation_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *BipowerVariation) Close() {
	if ind.handle != nil {
		C.wickra_bipower_variation_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// BodySizePct wraps the BodySizePct indicator over the Wickra C ABI.
type BodySizePct struct {
	handle *C.struct_BodySizePct
}

// NewBodySizePct constructs a BodySizePct. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewBodySizePct() (*BodySizePct, error) {
	ptr := C.wickra_body_size_pct_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &BodySizePct{handle: ptr}
	runtime.SetFinalizer(obj, (*BodySizePct).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *BodySizePct) WarmupPeriod() int {
	r := int(C.wickra_body_size_pct_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *BodySizePct) IsReady() bool {
	r := bool(C.wickra_body_size_pct_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *BodySizePct) Name() string {
	r := C.GoString(C.wickra_body_size_pct_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *BodySizePct) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_body_size_pct_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *BodySizePct) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_body_size_pct_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *BodySizePct) Reset() {
	C.wickra_body_size_pct_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *BodySizePct) Close() {
	if ind.handle != nil {
		C.wickra_body_size_pct_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// BollingerBands wraps the BollingerBands indicator over the Wickra C ABI.
type BollingerBands struct {
	handle *C.struct_BollingerBands
}

// NewBollingerBands constructs a BollingerBands. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewBollingerBands(period int, multiplier float64) (*BollingerBands, error) {
	ptr := C.wickra_bollinger_bands_new(C.uintptr_t(period), C.double(multiplier))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &BollingerBands{handle: ptr}
	runtime.SetFinalizer(obj, (*BollingerBands).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *BollingerBands) WarmupPeriod() int {
	r := int(C.wickra_bollinger_bands_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *BollingerBands) IsReady() bool {
	r := bool(C.wickra_bollinger_bands_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *BollingerBands) Name() string {
	r := C.GoString(C.wickra_bollinger_bands_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *BollingerBands) Update(value float64) (BollingerOutput, bool) {
	var out C.struct_WickraBollingerOutput
	ok := bool(C.wickra_bollinger_bands_update(ind.handle, C.double(value), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return BollingerOutput{}, false
	}
	return BollingerOutput{float64(out.upper), float64(out.middle), float64(out.lower), float64(out.stddev)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *BollingerBands) Reset() {
	C.wickra_bollinger_bands_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *BollingerBands) Close() {
	if ind.handle != nil {
		C.wickra_bollinger_bands_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// BollingerBandwidth wraps the BollingerBandwidth indicator over the Wickra C ABI.
type BollingerBandwidth struct {
	handle *C.struct_BollingerBandwidth
}

// NewBollingerBandwidth constructs a BollingerBandwidth. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewBollingerBandwidth(period int, multiplier float64) (*BollingerBandwidth, error) {
	ptr := C.wickra_bollinger_bandwidth_new(C.uintptr_t(period), C.double(multiplier))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &BollingerBandwidth{handle: ptr}
	runtime.SetFinalizer(obj, (*BollingerBandwidth).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *BollingerBandwidth) WarmupPeriod() int {
	r := int(C.wickra_bollinger_bandwidth_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *BollingerBandwidth) IsReady() bool {
	r := bool(C.wickra_bollinger_bandwidth_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *BollingerBandwidth) Name() string {
	r := C.GoString(C.wickra_bollinger_bandwidth_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *BollingerBandwidth) Update(value float64) float64 {
	r := float64(C.wickra_bollinger_bandwidth_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *BollingerBandwidth) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_bollinger_bandwidth_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *BollingerBandwidth) Reset() {
	C.wickra_bollinger_bandwidth_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *BollingerBandwidth) Close() {
	if ind.handle != nil {
		C.wickra_bollinger_bandwidth_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// BomarBands wraps the BomarBands indicator over the Wickra C ABI.
type BomarBands struct {
	handle *C.struct_BomarBands
}

// NewBomarBands constructs a BomarBands. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewBomarBands(period int, coverage float64) (*BomarBands, error) {
	ptr := C.wickra_bomar_bands_new(C.uintptr_t(period), C.double(coverage))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &BomarBands{handle: ptr}
	runtime.SetFinalizer(obj, (*BomarBands).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *BomarBands) WarmupPeriod() int {
	r := int(C.wickra_bomar_bands_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *BomarBands) IsReady() bool {
	r := bool(C.wickra_bomar_bands_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *BomarBands) Name() string {
	r := C.GoString(C.wickra_bomar_bands_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *BomarBands) Update(value float64) (BomarBandsOutput, bool) {
	var out C.struct_WickraBomarBandsOutput
	ok := bool(C.wickra_bomar_bands_update(ind.handle, C.double(value), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return BomarBandsOutput{}, false
	}
	return BomarBandsOutput{float64(out.upper), float64(out.middle), float64(out.lower)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *BomarBands) Reset() {
	C.wickra_bomar_bands_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *BomarBands) Close() {
	if ind.handle != nil {
		C.wickra_bomar_bands_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// BreadthThrust wraps the BreadthThrust indicator over the Wickra C ABI.
type BreadthThrust struct {
	handle *C.struct_BreadthThrust
}

// NewBreadthThrust constructs a BreadthThrust. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewBreadthThrust(period int) (*BreadthThrust, error) {
	ptr := C.wickra_breadth_thrust_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &BreadthThrust{handle: ptr}
	runtime.SetFinalizer(obj, (*BreadthThrust).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *BreadthThrust) WarmupPeriod() int {
	r := int(C.wickra_breadth_thrust_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *BreadthThrust) IsReady() bool {
	r := bool(C.wickra_breadth_thrust_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *BreadthThrust) Name() string {
	r := C.GoString(C.wickra_breadth_thrust_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *BreadthThrust) Update(change []float64, volume []float64, newHigh []bool, newLow []bool, aboveMa []bool, onBuySignal []bool, timestamp int64) float64 {
	if len(volume) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newHigh) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newLow) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(aboveMa) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(onBuySignal) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_breadth_thrust_update(ind.handle, (*C.double)(unsafe.Pointer(&change[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.bool)(unsafe.Pointer(&newHigh[0])), (*C.bool)(unsafe.Pointer(&newLow[0])), (*C.bool)(unsafe.Pointer(&aboveMa[0])), (*C.bool)(unsafe.Pointer(&onBuySignal[0])), C.uintptr_t(len(change)), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(change)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(newHigh)
	runtime.KeepAlive(newLow)
	runtime.KeepAlive(aboveMa)
	runtime.KeepAlive(onBuySignal)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *BreadthThrust) Reset() {
	C.wickra_breadth_thrust_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *BreadthThrust) Close() {
	if ind.handle != nil {
		C.wickra_breadth_thrust_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Breakaway wraps the Breakaway indicator over the Wickra C ABI.
type Breakaway struct {
	handle *C.struct_Breakaway
}

// NewBreakaway constructs a Breakaway. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewBreakaway() (*Breakaway, error) {
	ptr := C.wickra_breakaway_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Breakaway{handle: ptr}
	runtime.SetFinalizer(obj, (*Breakaway).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Breakaway) WarmupPeriod() int {
	r := int(C.wickra_breakaway_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Breakaway) IsReady() bool {
	r := bool(C.wickra_breakaway_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Breakaway) Name() string {
	r := C.GoString(C.wickra_breakaway_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Breakaway) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_breakaway_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Breakaway) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_breakaway_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Breakaway) Reset() {
	C.wickra_breakaway_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Breakaway) Close() {
	if ind.handle != nil {
		C.wickra_breakaway_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// BullishPercentIndex wraps the BullishPercentIndex indicator over the Wickra C ABI.
type BullishPercentIndex struct {
	handle *C.struct_BullishPercentIndex
}

// NewBullishPercentIndex constructs a BullishPercentIndex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewBullishPercentIndex() (*BullishPercentIndex, error) {
	ptr := C.wickra_bullish_percent_index_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &BullishPercentIndex{handle: ptr}
	runtime.SetFinalizer(obj, (*BullishPercentIndex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *BullishPercentIndex) WarmupPeriod() int {
	r := int(C.wickra_bullish_percent_index_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *BullishPercentIndex) IsReady() bool {
	r := bool(C.wickra_bullish_percent_index_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *BullishPercentIndex) Name() string {
	r := C.GoString(C.wickra_bullish_percent_index_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *BullishPercentIndex) Update(change []float64, volume []float64, newHigh []bool, newLow []bool, aboveMa []bool, onBuySignal []bool, timestamp int64) float64 {
	if len(volume) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newHigh) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newLow) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(aboveMa) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(onBuySignal) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_bullish_percent_index_update(ind.handle, (*C.double)(unsafe.Pointer(&change[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.bool)(unsafe.Pointer(&newHigh[0])), (*C.bool)(unsafe.Pointer(&newLow[0])), (*C.bool)(unsafe.Pointer(&aboveMa[0])), (*C.bool)(unsafe.Pointer(&onBuySignal[0])), C.uintptr_t(len(change)), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(change)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(newHigh)
	runtime.KeepAlive(newLow)
	runtime.KeepAlive(aboveMa)
	runtime.KeepAlive(onBuySignal)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *BullishPercentIndex) Reset() {
	C.wickra_bullish_percent_index_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *BullishPercentIndex) Close() {
	if ind.handle != nil {
		C.wickra_bullish_percent_index_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// BurkeRatio wraps the BurkeRatio indicator over the Wickra C ABI.
type BurkeRatio struct {
	handle *C.struct_BurkeRatio
}

// NewBurkeRatio constructs a BurkeRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewBurkeRatio(period int) (*BurkeRatio, error) {
	ptr := C.wickra_burke_ratio_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &BurkeRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*BurkeRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *BurkeRatio) WarmupPeriod() int {
	r := int(C.wickra_burke_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *BurkeRatio) IsReady() bool {
	r := bool(C.wickra_burke_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *BurkeRatio) Name() string {
	r := C.GoString(C.wickra_burke_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *BurkeRatio) Update(value float64) float64 {
	r := float64(C.wickra_burke_ratio_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *BurkeRatio) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_burke_ratio_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *BurkeRatio) Reset() {
	C.wickra_burke_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *BurkeRatio) Close() {
	if ind.handle != nil {
		C.wickra_burke_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Butterfly wraps the Butterfly indicator over the Wickra C ABI.
type Butterfly struct {
	handle *C.struct_Butterfly
}

// NewButterfly constructs a Butterfly. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewButterfly() (*Butterfly, error) {
	ptr := C.wickra_butterfly_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Butterfly{handle: ptr}
	runtime.SetFinalizer(obj, (*Butterfly).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Butterfly) WarmupPeriod() int {
	r := int(C.wickra_butterfly_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Butterfly) IsReady() bool {
	r := bool(C.wickra_butterfly_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Butterfly) Name() string {
	r := C.GoString(C.wickra_butterfly_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Butterfly) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_butterfly_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Butterfly) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_butterfly_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Butterfly) Reset() {
	C.wickra_butterfly_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Butterfly) Close() {
	if ind.handle != nil {
		C.wickra_butterfly_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// CalendarSpread wraps the CalendarSpread indicator over the Wickra C ABI.
type CalendarSpread struct {
	handle *C.struct_CalendarSpread
}

// NewCalendarSpread constructs a CalendarSpread. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCalendarSpread() (*CalendarSpread, error) {
	ptr := C.wickra_calendar_spread_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &CalendarSpread{handle: ptr}
	runtime.SetFinalizer(obj, (*CalendarSpread).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *CalendarSpread) WarmupPeriod() int {
	r := int(C.wickra_calendar_spread_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *CalendarSpread) IsReady() bool {
	r := bool(C.wickra_calendar_spread_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *CalendarSpread) Name() string {
	r := C.GoString(C.wickra_calendar_spread_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *CalendarSpread) Update(fundingRate float64, markPrice float64, indexPrice float64, futuresPrice float64, openInterest float64, longSize float64, shortSize float64, takerBuyVolume float64, takerSellVolume float64, longLiquidation float64, shortLiquidation float64, timestamp int64) float64 {
	r := float64(C.wickra_calendar_spread_update(ind.handle, C.double(fundingRate), C.double(markPrice), C.double(indexPrice), C.double(futuresPrice), C.double(openInterest), C.double(longSize), C.double(shortSize), C.double(takerBuyVolume), C.double(takerSellVolume), C.double(longLiquidation), C.double(shortLiquidation), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *CalendarSpread) Reset() {
	C.wickra_calendar_spread_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *CalendarSpread) Close() {
	if ind.handle != nil {
		C.wickra_calendar_spread_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// CalmarRatio wraps the CalmarRatio indicator over the Wickra C ABI.
type CalmarRatio struct {
	handle *C.struct_CalmarRatio
}

// NewCalmarRatio constructs a CalmarRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCalmarRatio(period int) (*CalmarRatio, error) {
	ptr := C.wickra_calmar_ratio_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &CalmarRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*CalmarRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *CalmarRatio) WarmupPeriod() int {
	r := int(C.wickra_calmar_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *CalmarRatio) IsReady() bool {
	r := bool(C.wickra_calmar_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *CalmarRatio) Name() string {
	r := C.GoString(C.wickra_calmar_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *CalmarRatio) Update(value float64) float64 {
	r := float64(C.wickra_calmar_ratio_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *CalmarRatio) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_calmar_ratio_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *CalmarRatio) Reset() {
	C.wickra_calmar_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *CalmarRatio) Close() {
	if ind.handle != nil {
		C.wickra_calmar_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Camarilla wraps the Camarilla indicator over the Wickra C ABI.
type Camarilla struct {
	handle *C.struct_Camarilla
}

// NewCamarilla constructs a Camarilla. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCamarilla() (*Camarilla, error) {
	ptr := C.wickra_camarilla_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Camarilla{handle: ptr}
	runtime.SetFinalizer(obj, (*Camarilla).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Camarilla) WarmupPeriod() int {
	r := int(C.wickra_camarilla_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Camarilla) IsReady() bool {
	r := bool(C.wickra_camarilla_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Camarilla) Name() string {
	r := C.GoString(C.wickra_camarilla_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *Camarilla) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (CamarillaPivotsOutput, bool) {
	var out C.struct_WickraCamarillaPivotsOutput
	ok := bool(C.wickra_camarilla_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return CamarillaPivotsOutput{}, false
	}
	return CamarillaPivotsOutput{float64(out.pp), float64(out.r1), float64(out.r2), float64(out.r3), float64(out.r4), float64(out.s1), float64(out.s2), float64(out.s3), float64(out.s4)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Camarilla) Reset() {
	C.wickra_camarilla_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Camarilla) Close() {
	if ind.handle != nil {
		C.wickra_camarilla_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// CandleReader parses an OHLCV CSV buffer into candles over the Wickra C ABI.
type CandleReader struct {
	handle *C.struct_CandleReader
}

// NewCandleReader parses a timestamp,open,high,low,close,volume CSV string (a
// leading UTF-8 BOM and field whitespace are tolerated). It returns
// ErrInvalidParams when the header or a row is malformed.
func NewCandleReader(csv string) (*CandleReader, error) {
	data := []byte(csv)
	var ptr *C.struct_CandleReader
	if len(data) == 0 {
		ptr = C.wickra_candle_reader_new(nil, 0)
	} else {
		ptr = C.wickra_candle_reader_new((*C.uint8_t)(unsafe.Pointer(&data[0])), C.uintptr_t(len(data)))
	}
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &CandleReader{handle: ptr}
	runtime.SetFinalizer(obj, (*CandleReader).Close)
	return obj, nil
}

// Read returns every candle parsed from the CSV, in file order.
func (ind *CandleReader) Read() []Candle {
	n := int(C.wickra_candle_reader_count(ind.handle))
	runtime.KeepAlive(ind)
	if n <= 0 {
		return nil
	}
	buf := make([]C.struct_WickraCandle, n)
	C.wickra_candle_reader_read(ind.handle, &buf[0], C.uintptr_t(n))
	runtime.KeepAlive(ind)
	out := make([]Candle, n)
	for i := 0; i < n; i++ {
		out[i] = Candle{float64(buf[i].open), float64(buf[i].high), float64(buf[i].low), float64(buf[i].close), float64(buf[i].volume), int64(buf[i].timestamp)}
	}
	return out
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *CandleReader) Close() {
	if ind.handle != nil {
		C.wickra_candle_reader_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// CandleVolume wraps the CandleVolume indicator over the Wickra C ABI.
type CandleVolume struct {
	handle *C.struct_CandleVolume
}

// NewCandleVolume constructs a CandleVolume. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCandleVolume(period int) (*CandleVolume, error) {
	ptr := C.wickra_candle_volume_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &CandleVolume{handle: ptr}
	runtime.SetFinalizer(obj, (*CandleVolume).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *CandleVolume) WarmupPeriod() int {
	r := int(C.wickra_candle_volume_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *CandleVolume) IsReady() bool {
	r := bool(C.wickra_candle_volume_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *CandleVolume) Name() string {
	r := C.GoString(C.wickra_candle_volume_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *CandleVolume) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (CandleVolumeOutput, bool) {
	var out C.struct_WickraCandleVolumeOutput
	ok := bool(C.wickra_candle_volume_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return CandleVolumeOutput{}, false
	}
	return CandleVolumeOutput{float64(out.body), float64(out.width)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *CandleVolume) Reset() {
	C.wickra_candle_volume_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *CandleVolume) Close() {
	if ind.handle != nil {
		C.wickra_candle_volume_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Cci wraps the Cci indicator over the Wickra C ABI.
type Cci struct {
	handle *C.struct_Cci
}

// NewCci constructs a Cci. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCci(period int) (*Cci, error) {
	ptr := C.wickra_cci_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Cci{handle: ptr}
	runtime.SetFinalizer(obj, (*Cci).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Cci) WarmupPeriod() int {
	r := int(C.wickra_cci_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Cci) IsReady() bool {
	r := bool(C.wickra_cci_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Cci) Name() string {
	r := C.GoString(C.wickra_cci_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Cci) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_cci_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Cci) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_cci_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Cci) Reset() {
	C.wickra_cci_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Cci) Close() {
	if ind.handle != nil {
		C.wickra_cci_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// CenterOfGravity wraps the CenterOfGravity indicator over the Wickra C ABI.
type CenterOfGravity struct {
	handle *C.struct_CenterOfGravity
}

// NewCenterOfGravity constructs a CenterOfGravity. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCenterOfGravity(period int) (*CenterOfGravity, error) {
	ptr := C.wickra_center_of_gravity_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &CenterOfGravity{handle: ptr}
	runtime.SetFinalizer(obj, (*CenterOfGravity).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *CenterOfGravity) WarmupPeriod() int {
	r := int(C.wickra_center_of_gravity_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *CenterOfGravity) IsReady() bool {
	r := bool(C.wickra_center_of_gravity_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *CenterOfGravity) Name() string {
	r := C.GoString(C.wickra_center_of_gravity_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *CenterOfGravity) Update(value float64) float64 {
	r := float64(C.wickra_center_of_gravity_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *CenterOfGravity) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_center_of_gravity_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *CenterOfGravity) Reset() {
	C.wickra_center_of_gravity_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *CenterOfGravity) Close() {
	if ind.handle != nil {
		C.wickra_center_of_gravity_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// CentralPivotRange wraps the CentralPivotRange indicator over the Wickra C ABI.
type CentralPivotRange struct {
	handle *C.struct_CentralPivotRange
}

// NewCentralPivotRange constructs a CentralPivotRange. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCentralPivotRange() (*CentralPivotRange, error) {
	ptr := C.wickra_central_pivot_range_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &CentralPivotRange{handle: ptr}
	runtime.SetFinalizer(obj, (*CentralPivotRange).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *CentralPivotRange) WarmupPeriod() int {
	r := int(C.wickra_central_pivot_range_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *CentralPivotRange) IsReady() bool {
	r := bool(C.wickra_central_pivot_range_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *CentralPivotRange) Name() string {
	r := C.GoString(C.wickra_central_pivot_range_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *CentralPivotRange) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (CentralPivotRangeOutput, bool) {
	var out C.struct_WickraCentralPivotRangeOutput
	ok := bool(C.wickra_central_pivot_range_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return CentralPivotRangeOutput{}, false
	}
	return CentralPivotRangeOutput{float64(out.pivot), float64(out.tc), float64(out.bc)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *CentralPivotRange) Reset() {
	C.wickra_central_pivot_range_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *CentralPivotRange) Close() {
	if ind.handle != nil {
		C.wickra_central_pivot_range_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Cfo wraps the Cfo indicator over the Wickra C ABI.
type Cfo struct {
	handle *C.struct_Cfo
}

// NewCfo constructs a Cfo. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCfo(period int) (*Cfo, error) {
	ptr := C.wickra_cfo_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Cfo{handle: ptr}
	runtime.SetFinalizer(obj, (*Cfo).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Cfo) WarmupPeriod() int {
	r := int(C.wickra_cfo_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Cfo) IsReady() bool {
	r := bool(C.wickra_cfo_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Cfo) Name() string {
	r := C.GoString(C.wickra_cfo_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Cfo) Update(value float64) float64 {
	r := float64(C.wickra_cfo_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Cfo) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_cfo_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Cfo) Reset() {
	C.wickra_cfo_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Cfo) Close() {
	if ind.handle != nil {
		C.wickra_cfo_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ChaikinMoneyFlow wraps the ChaikinMoneyFlow indicator over the Wickra C ABI.
type ChaikinMoneyFlow struct {
	handle *C.struct_ChaikinMoneyFlow
}

// NewChaikinMoneyFlow constructs a ChaikinMoneyFlow. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewChaikinMoneyFlow(period int) (*ChaikinMoneyFlow, error) {
	ptr := C.wickra_chaikin_money_flow_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ChaikinMoneyFlow{handle: ptr}
	runtime.SetFinalizer(obj, (*ChaikinMoneyFlow).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ChaikinMoneyFlow) WarmupPeriod() int {
	r := int(C.wickra_chaikin_money_flow_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ChaikinMoneyFlow) IsReady() bool {
	r := bool(C.wickra_chaikin_money_flow_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ChaikinMoneyFlow) Name() string {
	r := C.GoString(C.wickra_chaikin_money_flow_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ChaikinMoneyFlow) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_chaikin_money_flow_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ChaikinMoneyFlow) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_chaikin_money_flow_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ChaikinMoneyFlow) Reset() {
	C.wickra_chaikin_money_flow_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ChaikinMoneyFlow) Close() {
	if ind.handle != nil {
		C.wickra_chaikin_money_flow_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ChaikinOscillator wraps the ChaikinOscillator indicator over the Wickra C ABI.
type ChaikinOscillator struct {
	handle *C.struct_ChaikinOscillator
}

// NewChaikinOscillator constructs a ChaikinOscillator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewChaikinOscillator(fast int, slow int) (*ChaikinOscillator, error) {
	ptr := C.wickra_chaikin_oscillator_new(C.uintptr_t(fast), C.uintptr_t(slow))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ChaikinOscillator{handle: ptr}
	runtime.SetFinalizer(obj, (*ChaikinOscillator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ChaikinOscillator) WarmupPeriod() int {
	r := int(C.wickra_chaikin_oscillator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ChaikinOscillator) IsReady() bool {
	r := bool(C.wickra_chaikin_oscillator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ChaikinOscillator) Name() string {
	r := C.GoString(C.wickra_chaikin_oscillator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ChaikinOscillator) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_chaikin_oscillator_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ChaikinOscillator) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_chaikin_oscillator_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ChaikinOscillator) Reset() {
	C.wickra_chaikin_oscillator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ChaikinOscillator) Close() {
	if ind.handle != nil {
		C.wickra_chaikin_oscillator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ChaikinVolatility wraps the ChaikinVolatility indicator over the Wickra C ABI.
type ChaikinVolatility struct {
	handle *C.struct_ChaikinVolatility
}

// NewChaikinVolatility constructs a ChaikinVolatility. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewChaikinVolatility(emaPeriod int, rocPeriod int) (*ChaikinVolatility, error) {
	ptr := C.wickra_chaikin_volatility_new(C.uintptr_t(emaPeriod), C.uintptr_t(rocPeriod))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ChaikinVolatility{handle: ptr}
	runtime.SetFinalizer(obj, (*ChaikinVolatility).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ChaikinVolatility) WarmupPeriod() int {
	r := int(C.wickra_chaikin_volatility_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ChaikinVolatility) IsReady() bool {
	r := bool(C.wickra_chaikin_volatility_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ChaikinVolatility) Name() string {
	r := C.GoString(C.wickra_chaikin_volatility_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ChaikinVolatility) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_chaikin_volatility_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ChaikinVolatility) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_chaikin_volatility_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ChaikinVolatility) Reset() {
	C.wickra_chaikin_volatility_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ChaikinVolatility) Close() {
	if ind.handle != nil {
		C.wickra_chaikin_volatility_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ChandeKrollStop wraps the ChandeKrollStop indicator over the Wickra C ABI.
type ChandeKrollStop struct {
	handle *C.struct_ChandeKrollStop
}

// NewChandeKrollStop constructs a ChandeKrollStop. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewChandeKrollStop(atrPeriod int, atrMultiplier float64, stopPeriod int) (*ChandeKrollStop, error) {
	ptr := C.wickra_chande_kroll_stop_new(C.uintptr_t(atrPeriod), C.double(atrMultiplier), C.uintptr_t(stopPeriod))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ChandeKrollStop{handle: ptr}
	runtime.SetFinalizer(obj, (*ChandeKrollStop).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ChandeKrollStop) WarmupPeriod() int {
	r := int(C.wickra_chande_kroll_stop_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ChandeKrollStop) IsReady() bool {
	r := bool(C.wickra_chande_kroll_stop_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ChandeKrollStop) Name() string {
	r := C.GoString(C.wickra_chande_kroll_stop_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *ChandeKrollStop) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (ChandeKrollStopOutput, bool) {
	var out C.struct_WickraChandeKrollStopOutput
	ok := bool(C.wickra_chande_kroll_stop_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return ChandeKrollStopOutput{}, false
	}
	return ChandeKrollStopOutput{float64(out.stop_long), float64(out.stop_short)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ChandeKrollStop) Reset() {
	C.wickra_chande_kroll_stop_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ChandeKrollStop) Close() {
	if ind.handle != nil {
		C.wickra_chande_kroll_stop_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ChandelierExit wraps the ChandelierExit indicator over the Wickra C ABI.
type ChandelierExit struct {
	handle *C.struct_ChandelierExit
}

// NewChandelierExit constructs a ChandelierExit. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewChandelierExit(period int, multiplier float64) (*ChandelierExit, error) {
	ptr := C.wickra_chandelier_exit_new(C.uintptr_t(period), C.double(multiplier))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ChandelierExit{handle: ptr}
	runtime.SetFinalizer(obj, (*ChandelierExit).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ChandelierExit) WarmupPeriod() int {
	r := int(C.wickra_chandelier_exit_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ChandelierExit) IsReady() bool {
	r := bool(C.wickra_chandelier_exit_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ChandelierExit) Name() string {
	r := C.GoString(C.wickra_chandelier_exit_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *ChandelierExit) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (ChandelierExitOutput, bool) {
	var out C.struct_WickraChandelierExitOutput
	ok := bool(C.wickra_chandelier_exit_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return ChandelierExitOutput{}, false
	}
	return ChandelierExitOutput{float64(out.long_stop), float64(out.short_stop)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ChandelierExit) Reset() {
	C.wickra_chandelier_exit_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ChandelierExit) Close() {
	if ind.handle != nil {
		C.wickra_chandelier_exit_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ChoppinessIndex wraps the ChoppinessIndex indicator over the Wickra C ABI.
type ChoppinessIndex struct {
	handle *C.struct_ChoppinessIndex
}

// NewChoppinessIndex constructs a ChoppinessIndex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewChoppinessIndex(period int) (*ChoppinessIndex, error) {
	ptr := C.wickra_choppiness_index_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ChoppinessIndex{handle: ptr}
	runtime.SetFinalizer(obj, (*ChoppinessIndex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ChoppinessIndex) WarmupPeriod() int {
	r := int(C.wickra_choppiness_index_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ChoppinessIndex) IsReady() bool {
	r := bool(C.wickra_choppiness_index_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ChoppinessIndex) Name() string {
	r := C.GoString(C.wickra_choppiness_index_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ChoppinessIndex) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_choppiness_index_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ChoppinessIndex) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_choppiness_index_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ChoppinessIndex) Reset() {
	C.wickra_choppiness_index_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ChoppinessIndex) Close() {
	if ind.handle != nil {
		C.wickra_choppiness_index_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ClassicPivots wraps the ClassicPivots indicator over the Wickra C ABI.
type ClassicPivots struct {
	handle *C.struct_ClassicPivots
}

// NewClassicPivots constructs a ClassicPivots. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewClassicPivots() (*ClassicPivots, error) {
	ptr := C.wickra_classic_pivots_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ClassicPivots{handle: ptr}
	runtime.SetFinalizer(obj, (*ClassicPivots).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ClassicPivots) WarmupPeriod() int {
	r := int(C.wickra_classic_pivots_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ClassicPivots) IsReady() bool {
	r := bool(C.wickra_classic_pivots_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ClassicPivots) Name() string {
	r := C.GoString(C.wickra_classic_pivots_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *ClassicPivots) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (ClassicPivotsOutput, bool) {
	var out C.struct_WickraClassicPivotsOutput
	ok := bool(C.wickra_classic_pivots_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return ClassicPivotsOutput{}, false
	}
	return ClassicPivotsOutput{float64(out.pp), float64(out.r1), float64(out.r2), float64(out.r3), float64(out.s1), float64(out.s2), float64(out.s3)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ClassicPivots) Reset() {
	C.wickra_classic_pivots_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ClassicPivots) Close() {
	if ind.handle != nil {
		C.wickra_classic_pivots_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// CloseVsOpen wraps the CloseVsOpen indicator over the Wickra C ABI.
type CloseVsOpen struct {
	handle *C.struct_CloseVsOpen
}

// NewCloseVsOpen constructs a CloseVsOpen. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCloseVsOpen() (*CloseVsOpen, error) {
	ptr := C.wickra_close_vs_open_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &CloseVsOpen{handle: ptr}
	runtime.SetFinalizer(obj, (*CloseVsOpen).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *CloseVsOpen) WarmupPeriod() int {
	r := int(C.wickra_close_vs_open_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *CloseVsOpen) IsReady() bool {
	r := bool(C.wickra_close_vs_open_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *CloseVsOpen) Name() string {
	r := C.GoString(C.wickra_close_vs_open_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *CloseVsOpen) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_close_vs_open_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *CloseVsOpen) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_close_vs_open_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *CloseVsOpen) Reset() {
	C.wickra_close_vs_open_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *CloseVsOpen) Close() {
	if ind.handle != nil {
		C.wickra_close_vs_open_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ClosingMarubozu wraps the ClosingMarubozu indicator over the Wickra C ABI.
type ClosingMarubozu struct {
	handle *C.struct_ClosingMarubozu
}

// NewClosingMarubozu constructs a ClosingMarubozu. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewClosingMarubozu() (*ClosingMarubozu, error) {
	ptr := C.wickra_closing_marubozu_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ClosingMarubozu{handle: ptr}
	runtime.SetFinalizer(obj, (*ClosingMarubozu).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ClosingMarubozu) WarmupPeriod() int {
	r := int(C.wickra_closing_marubozu_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ClosingMarubozu) IsReady() bool {
	r := bool(C.wickra_closing_marubozu_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ClosingMarubozu) Name() string {
	r := C.GoString(C.wickra_closing_marubozu_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ClosingMarubozu) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_closing_marubozu_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ClosingMarubozu) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_closing_marubozu_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ClosingMarubozu) Reset() {
	C.wickra_closing_marubozu_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ClosingMarubozu) Close() {
	if ind.handle != nil {
		C.wickra_closing_marubozu_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Cmo wraps the Cmo indicator over the Wickra C ABI.
type Cmo struct {
	handle *C.struct_Cmo
}

// NewCmo constructs a Cmo. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCmo(period int) (*Cmo, error) {
	ptr := C.wickra_cmo_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Cmo{handle: ptr}
	runtime.SetFinalizer(obj, (*Cmo).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Cmo) WarmupPeriod() int {
	r := int(C.wickra_cmo_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Cmo) IsReady() bool {
	r := bool(C.wickra_cmo_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Cmo) Name() string {
	r := C.GoString(C.wickra_cmo_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Cmo) Update(value float64) float64 {
	r := float64(C.wickra_cmo_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Cmo) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_cmo_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Cmo) Reset() {
	C.wickra_cmo_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Cmo) Close() {
	if ind.handle != nil {
		C.wickra_cmo_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// CoefficientOfVariation wraps the CoefficientOfVariation indicator over the Wickra C ABI.
type CoefficientOfVariation struct {
	handle *C.struct_CoefficientOfVariation
}

// NewCoefficientOfVariation constructs a CoefficientOfVariation. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCoefficientOfVariation(period int) (*CoefficientOfVariation, error) {
	ptr := C.wickra_coefficient_of_variation_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &CoefficientOfVariation{handle: ptr}
	runtime.SetFinalizer(obj, (*CoefficientOfVariation).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *CoefficientOfVariation) WarmupPeriod() int {
	r := int(C.wickra_coefficient_of_variation_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *CoefficientOfVariation) IsReady() bool {
	r := bool(C.wickra_coefficient_of_variation_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *CoefficientOfVariation) Name() string {
	r := C.GoString(C.wickra_coefficient_of_variation_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *CoefficientOfVariation) Update(value float64) float64 {
	r := float64(C.wickra_coefficient_of_variation_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *CoefficientOfVariation) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_coefficient_of_variation_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *CoefficientOfVariation) Reset() {
	C.wickra_coefficient_of_variation_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *CoefficientOfVariation) Close() {
	if ind.handle != nil {
		C.wickra_coefficient_of_variation_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Cointegration wraps the Cointegration indicator over the Wickra C ABI.
type Cointegration struct {
	handle *C.struct_Cointegration
}

// NewCointegration constructs a Cointegration. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCointegration(period int, adfLags int) (*Cointegration, error) {
	ptr := C.wickra_cointegration_new(C.uintptr_t(period), C.uintptr_t(adfLags))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Cointegration{handle: ptr}
	runtime.SetFinalizer(obj, (*Cointegration).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Cointegration) WarmupPeriod() int {
	r := int(C.wickra_cointegration_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Cointegration) IsReady() bool {
	r := bool(C.wickra_cointegration_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Cointegration) Name() string {
	r := C.GoString(C.wickra_cointegration_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *Cointegration) Update(x float64, y float64) (CointegrationOutput, bool) {
	var out C.struct_WickraCointegrationOutput
	ok := bool(C.wickra_cointegration_update(ind.handle, C.double(x), C.double(y), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return CointegrationOutput{}, false
	}
	return CointegrationOutput{float64(out.hedge_ratio), float64(out.spread), float64(out.adf_stat)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Cointegration) Reset() {
	C.wickra_cointegration_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Cointegration) Close() {
	if ind.handle != nil {
		C.wickra_cointegration_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// CommonSenseRatio wraps the CommonSenseRatio indicator over the Wickra C ABI.
type CommonSenseRatio struct {
	handle *C.struct_CommonSenseRatio
}

// NewCommonSenseRatio constructs a CommonSenseRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCommonSenseRatio(period int) (*CommonSenseRatio, error) {
	ptr := C.wickra_common_sense_ratio_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &CommonSenseRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*CommonSenseRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *CommonSenseRatio) WarmupPeriod() int {
	r := int(C.wickra_common_sense_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *CommonSenseRatio) IsReady() bool {
	r := bool(C.wickra_common_sense_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *CommonSenseRatio) Name() string {
	r := C.GoString(C.wickra_common_sense_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *CommonSenseRatio) Update(value float64) float64 {
	r := float64(C.wickra_common_sense_ratio_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *CommonSenseRatio) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_common_sense_ratio_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *CommonSenseRatio) Reset() {
	C.wickra_common_sense_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *CommonSenseRatio) Close() {
	if ind.handle != nil {
		C.wickra_common_sense_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// CompositeProfile wraps the CompositeProfile indicator over the Wickra C ABI.
type CompositeProfile struct {
	handle *C.struct_CompositeProfile
}

// NewCompositeProfile constructs a CompositeProfile. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCompositeProfile(period int, bins int, valueAreaPct float64) (*CompositeProfile, error) {
	ptr := C.wickra_composite_profile_new(C.uintptr_t(period), C.uintptr_t(bins), C.double(valueAreaPct))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &CompositeProfile{handle: ptr}
	runtime.SetFinalizer(obj, (*CompositeProfile).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *CompositeProfile) WarmupPeriod() int {
	r := int(C.wickra_composite_profile_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *CompositeProfile) IsReady() bool {
	r := bool(C.wickra_composite_profile_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *CompositeProfile) Name() string {
	r := C.GoString(C.wickra_composite_profile_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *CompositeProfile) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (CompositeProfileOutput, bool) {
	var out C.struct_WickraCompositeProfileOutput
	ok := bool(C.wickra_composite_profile_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return CompositeProfileOutput{}, false
	}
	return CompositeProfileOutput{float64(out.poc), float64(out.vah), float64(out.val)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *CompositeProfile) Reset() {
	C.wickra_composite_profile_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *CompositeProfile) Close() {
	if ind.handle != nil {
		C.wickra_composite_profile_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ConcealingBabySwallow wraps the ConcealingBabySwallow indicator over the Wickra C ABI.
type ConcealingBabySwallow struct {
	handle *C.struct_ConcealingBabySwallow
}

// NewConcealingBabySwallow constructs a ConcealingBabySwallow. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewConcealingBabySwallow() (*ConcealingBabySwallow, error) {
	ptr := C.wickra_concealing_baby_swallow_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ConcealingBabySwallow{handle: ptr}
	runtime.SetFinalizer(obj, (*ConcealingBabySwallow).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ConcealingBabySwallow) WarmupPeriod() int {
	r := int(C.wickra_concealing_baby_swallow_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ConcealingBabySwallow) IsReady() bool {
	r := bool(C.wickra_concealing_baby_swallow_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ConcealingBabySwallow) Name() string {
	r := C.GoString(C.wickra_concealing_baby_swallow_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ConcealingBabySwallow) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_concealing_baby_swallow_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ConcealingBabySwallow) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_concealing_baby_swallow_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ConcealingBabySwallow) Reset() {
	C.wickra_concealing_baby_swallow_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ConcealingBabySwallow) Close() {
	if ind.handle != nil {
		C.wickra_concealing_baby_swallow_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ConditionalValueAtRisk wraps the ConditionalValueAtRisk indicator over the Wickra C ABI.
type ConditionalValueAtRisk struct {
	handle *C.struct_ConditionalValueAtRisk
}

// NewConditionalValueAtRisk constructs a ConditionalValueAtRisk. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewConditionalValueAtRisk(period int, confidence float64) (*ConditionalValueAtRisk, error) {
	ptr := C.wickra_conditional_value_at_risk_new(C.uintptr_t(period), C.double(confidence))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ConditionalValueAtRisk{handle: ptr}
	runtime.SetFinalizer(obj, (*ConditionalValueAtRisk).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ConditionalValueAtRisk) WarmupPeriod() int {
	r := int(C.wickra_conditional_value_at_risk_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ConditionalValueAtRisk) IsReady() bool {
	r := bool(C.wickra_conditional_value_at_risk_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ConditionalValueAtRisk) Name() string {
	r := C.GoString(C.wickra_conditional_value_at_risk_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ConditionalValueAtRisk) Update(value float64) float64 {
	r := float64(C.wickra_conditional_value_at_risk_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ConditionalValueAtRisk) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_conditional_value_at_risk_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ConditionalValueAtRisk) Reset() {
	C.wickra_conditional_value_at_risk_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ConditionalValueAtRisk) Close() {
	if ind.handle != nil {
		C.wickra_conditional_value_at_risk_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ConnorsRsi wraps the ConnorsRsi indicator over the Wickra C ABI.
type ConnorsRsi struct {
	handle *C.struct_ConnorsRsi
}

// NewConnorsRsi constructs a ConnorsRsi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewConnorsRsi(periodRsi int, periodStreak int, periodRank int) (*ConnorsRsi, error) {
	ptr := C.wickra_connors_rsi_new(C.uintptr_t(periodRsi), C.uintptr_t(periodStreak), C.uintptr_t(periodRank))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ConnorsRsi{handle: ptr}
	runtime.SetFinalizer(obj, (*ConnorsRsi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ConnorsRsi) WarmupPeriod() int {
	r := int(C.wickra_connors_rsi_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ConnorsRsi) IsReady() bool {
	r := bool(C.wickra_connors_rsi_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ConnorsRsi) Name() string {
	r := C.GoString(C.wickra_connors_rsi_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ConnorsRsi) Update(value float64) float64 {
	r := float64(C.wickra_connors_rsi_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ConnorsRsi) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_connors_rsi_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ConnorsRsi) Reset() {
	C.wickra_connors_rsi_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ConnorsRsi) Close() {
	if ind.handle != nil {
		C.wickra_connors_rsi_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Coppock wraps the Coppock indicator over the Wickra C ABI.
type Coppock struct {
	handle *C.struct_Coppock
}

// NewCoppock constructs a Coppock. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCoppock(rocLongPeriod int, rocShortPeriod int, wmaPeriod int) (*Coppock, error) {
	ptr := C.wickra_coppock_new(C.uintptr_t(rocLongPeriod), C.uintptr_t(rocShortPeriod), C.uintptr_t(wmaPeriod))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Coppock{handle: ptr}
	runtime.SetFinalizer(obj, (*Coppock).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Coppock) WarmupPeriod() int {
	r := int(C.wickra_coppock_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Coppock) IsReady() bool {
	r := bool(C.wickra_coppock_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Coppock) Name() string {
	r := C.GoString(C.wickra_coppock_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Coppock) Update(value float64) float64 {
	r := float64(C.wickra_coppock_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Coppock) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_coppock_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Coppock) Reset() {
	C.wickra_coppock_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Coppock) Close() {
	if ind.handle != nil {
		C.wickra_coppock_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// CorrelationTrendIndicator wraps the CorrelationTrendIndicator indicator over the Wickra C ABI.
type CorrelationTrendIndicator struct {
	handle *C.struct_CorrelationTrendIndicator
}

// NewCorrelationTrendIndicator constructs a CorrelationTrendIndicator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCorrelationTrendIndicator(period int) (*CorrelationTrendIndicator, error) {
	ptr := C.wickra_correlation_trend_indicator_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &CorrelationTrendIndicator{handle: ptr}
	runtime.SetFinalizer(obj, (*CorrelationTrendIndicator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *CorrelationTrendIndicator) WarmupPeriod() int {
	r := int(C.wickra_correlation_trend_indicator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *CorrelationTrendIndicator) IsReady() bool {
	r := bool(C.wickra_correlation_trend_indicator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *CorrelationTrendIndicator) Name() string {
	r := C.GoString(C.wickra_correlation_trend_indicator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *CorrelationTrendIndicator) Update(value float64) float64 {
	r := float64(C.wickra_correlation_trend_indicator_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *CorrelationTrendIndicator) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_correlation_trend_indicator_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *CorrelationTrendIndicator) Reset() {
	C.wickra_correlation_trend_indicator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *CorrelationTrendIndicator) Close() {
	if ind.handle != nil {
		C.wickra_correlation_trend_indicator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Counterattack wraps the Counterattack indicator over the Wickra C ABI.
type Counterattack struct {
	handle *C.struct_Counterattack
}

// NewCounterattack constructs a Counterattack. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCounterattack() (*Counterattack, error) {
	ptr := C.wickra_counterattack_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Counterattack{handle: ptr}
	runtime.SetFinalizer(obj, (*Counterattack).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Counterattack) WarmupPeriod() int {
	r := int(C.wickra_counterattack_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Counterattack) IsReady() bool {
	r := bool(C.wickra_counterattack_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Counterattack) Name() string {
	r := C.GoString(C.wickra_counterattack_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Counterattack) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_counterattack_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Counterattack) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_counterattack_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Counterattack) Reset() {
	C.wickra_counterattack_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Counterattack) Close() {
	if ind.handle != nil {
		C.wickra_counterattack_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Crab wraps the Crab indicator over the Wickra C ABI.
type Crab struct {
	handle *C.struct_Crab
}

// NewCrab constructs a Crab. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCrab() (*Crab, error) {
	ptr := C.wickra_crab_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Crab{handle: ptr}
	runtime.SetFinalizer(obj, (*Crab).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Crab) WarmupPeriod() int {
	r := int(C.wickra_crab_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Crab) IsReady() bool {
	r := bool(C.wickra_crab_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Crab) Name() string {
	r := C.GoString(C.wickra_crab_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Crab) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_crab_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Crab) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_crab_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Crab) Reset() {
	C.wickra_crab_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Crab) Close() {
	if ind.handle != nil {
		C.wickra_crab_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// CumulativeVolumeDelta wraps the CumulativeVolumeDelta indicator over the Wickra C ABI.
type CumulativeVolumeDelta struct {
	handle *C.struct_CumulativeVolumeDelta
}

// NewCumulativeVolumeDelta constructs a CumulativeVolumeDelta. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCumulativeVolumeDelta() (*CumulativeVolumeDelta, error) {
	ptr := C.wickra_cumulative_volume_delta_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &CumulativeVolumeDelta{handle: ptr}
	runtime.SetFinalizer(obj, (*CumulativeVolumeDelta).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *CumulativeVolumeDelta) WarmupPeriod() int {
	r := int(C.wickra_cumulative_volume_delta_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *CumulativeVolumeDelta) IsReady() bool {
	r := bool(C.wickra_cumulative_volume_delta_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *CumulativeVolumeDelta) Name() string {
	r := C.GoString(C.wickra_cumulative_volume_delta_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *CumulativeVolumeDelta) Update(price float64, size float64, isBuy bool, timestamp int64) float64 {
	r := float64(C.wickra_cumulative_volume_delta_update(ind.handle, C.double(price), C.double(size), C.bool(isBuy), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *CumulativeVolumeDelta) Reset() {
	C.wickra_cumulative_volume_delta_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *CumulativeVolumeDelta) Close() {
	if ind.handle != nil {
		C.wickra_cumulative_volume_delta_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// CumulativeVolumeIndex wraps the CumulativeVolumeIndex indicator over the Wickra C ABI.
type CumulativeVolumeIndex struct {
	handle *C.struct_CumulativeVolumeIndex
}

// NewCumulativeVolumeIndex constructs a CumulativeVolumeIndex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCumulativeVolumeIndex() (*CumulativeVolumeIndex, error) {
	ptr := C.wickra_cumulative_volume_index_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &CumulativeVolumeIndex{handle: ptr}
	runtime.SetFinalizer(obj, (*CumulativeVolumeIndex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *CumulativeVolumeIndex) WarmupPeriod() int {
	r := int(C.wickra_cumulative_volume_index_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *CumulativeVolumeIndex) IsReady() bool {
	r := bool(C.wickra_cumulative_volume_index_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *CumulativeVolumeIndex) Name() string {
	r := C.GoString(C.wickra_cumulative_volume_index_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *CumulativeVolumeIndex) Update(change []float64, volume []float64, newHigh []bool, newLow []bool, aboveMa []bool, onBuySignal []bool, timestamp int64) float64 {
	if len(volume) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newHigh) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newLow) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(aboveMa) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(onBuySignal) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_cumulative_volume_index_update(ind.handle, (*C.double)(unsafe.Pointer(&change[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.bool)(unsafe.Pointer(&newHigh[0])), (*C.bool)(unsafe.Pointer(&newLow[0])), (*C.bool)(unsafe.Pointer(&aboveMa[0])), (*C.bool)(unsafe.Pointer(&onBuySignal[0])), C.uintptr_t(len(change)), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(change)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(newHigh)
	runtime.KeepAlive(newLow)
	runtime.KeepAlive(aboveMa)
	runtime.KeepAlive(onBuySignal)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *CumulativeVolumeIndex) Reset() {
	C.wickra_cumulative_volume_index_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *CumulativeVolumeIndex) Close() {
	if ind.handle != nil {
		C.wickra_cumulative_volume_index_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// CupAndHandle wraps the CupAndHandle indicator over the Wickra C ABI.
type CupAndHandle struct {
	handle *C.struct_CupAndHandle
}

// NewCupAndHandle constructs a CupAndHandle. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCupAndHandle() (*CupAndHandle, error) {
	ptr := C.wickra_cup_and_handle_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &CupAndHandle{handle: ptr}
	runtime.SetFinalizer(obj, (*CupAndHandle).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *CupAndHandle) WarmupPeriod() int {
	r := int(C.wickra_cup_and_handle_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *CupAndHandle) IsReady() bool {
	r := bool(C.wickra_cup_and_handle_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *CupAndHandle) Name() string {
	r := C.GoString(C.wickra_cup_and_handle_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *CupAndHandle) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_cup_and_handle_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *CupAndHandle) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_cup_and_handle_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *CupAndHandle) Reset() {
	C.wickra_cup_and_handle_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *CupAndHandle) Close() {
	if ind.handle != nil {
		C.wickra_cup_and_handle_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// CyberneticCycle wraps the CyberneticCycle indicator over the Wickra C ABI.
type CyberneticCycle struct {
	handle *C.struct_CyberneticCycle
}

// NewCyberneticCycle constructs a CyberneticCycle. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCyberneticCycle(period int) (*CyberneticCycle, error) {
	ptr := C.wickra_cybernetic_cycle_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &CyberneticCycle{handle: ptr}
	runtime.SetFinalizer(obj, (*CyberneticCycle).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *CyberneticCycle) WarmupPeriod() int {
	r := int(C.wickra_cybernetic_cycle_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *CyberneticCycle) IsReady() bool {
	r := bool(C.wickra_cybernetic_cycle_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *CyberneticCycle) Name() string {
	r := C.GoString(C.wickra_cybernetic_cycle_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *CyberneticCycle) Update(value float64) float64 {
	r := float64(C.wickra_cybernetic_cycle_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *CyberneticCycle) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_cybernetic_cycle_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *CyberneticCycle) Reset() {
	C.wickra_cybernetic_cycle_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *CyberneticCycle) Close() {
	if ind.handle != nil {
		C.wickra_cybernetic_cycle_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Cypher wraps the Cypher indicator over the Wickra C ABI.
type Cypher struct {
	handle *C.struct_Cypher
}

// NewCypher constructs a Cypher. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewCypher() (*Cypher, error) {
	ptr := C.wickra_cypher_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Cypher{handle: ptr}
	runtime.SetFinalizer(obj, (*Cypher).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Cypher) WarmupPeriod() int {
	r := int(C.wickra_cypher_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Cypher) IsReady() bool {
	r := bool(C.wickra_cypher_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Cypher) Name() string {
	r := C.GoString(C.wickra_cypher_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Cypher) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_cypher_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Cypher) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_cypher_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Cypher) Reset() {
	C.wickra_cypher_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Cypher) Close() {
	if ind.handle != nil {
		C.wickra_cypher_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// DayOfWeekProfile wraps the DayOfWeekProfile indicator over the Wickra C ABI.
type DayOfWeekProfile struct {
	handle    *C.struct_DayOfWeekProfile
	valuesCap int
}

// NewDayOfWeekProfile constructs a DayOfWeekProfile. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDayOfWeekProfile(utcOffsetMinutes int32) (*DayOfWeekProfile, error) {
	ptr := C.wickra_day_of_week_profile_new(C.int32_t(utcOffsetMinutes))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &DayOfWeekProfile{handle: ptr}
	obj.valuesCap = 4096
	runtime.SetFinalizer(obj, (*DayOfWeekProfile).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *DayOfWeekProfile) WarmupPeriod() int {
	r := int(C.wickra_day_of_week_profile_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *DayOfWeekProfile) IsReady() bool {
	r := bool(C.wickra_day_of_week_profile_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *DayOfWeekProfile) Name() string {
	r := C.GoString(C.wickra_day_of_week_profile_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the profile values
// (ok is false during warmup).
func (ind *DayOfWeekProfile) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) ([]float64, bool) {
	values := make([]float64, ind.valuesCap)
	n := int(C.wickra_day_of_week_profile_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), (*C.double)(unsafe.Pointer(&values[0])), C.uintptr_t(len(values))))
	runtime.KeepAlive(ind)
	if n < 0 {
		return nil, false
	}
	return values[:n], true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *DayOfWeekProfile) Reset() {
	C.wickra_day_of_week_profile_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *DayOfWeekProfile) Close() {
	if ind.handle != nil {
		C.wickra_day_of_week_profile_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Decycler wraps the Decycler indicator over the Wickra C ABI.
type Decycler struct {
	handle *C.struct_Decycler
}

// NewDecycler constructs a Decycler. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDecycler(period int) (*Decycler, error) {
	ptr := C.wickra_decycler_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Decycler{handle: ptr}
	runtime.SetFinalizer(obj, (*Decycler).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Decycler) WarmupPeriod() int {
	r := int(C.wickra_decycler_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Decycler) IsReady() bool {
	r := bool(C.wickra_decycler_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Decycler) Name() string {
	r := C.GoString(C.wickra_decycler_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Decycler) Update(value float64) float64 {
	r := float64(C.wickra_decycler_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Decycler) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_decycler_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Decycler) Reset() {
	C.wickra_decycler_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Decycler) Close() {
	if ind.handle != nil {
		C.wickra_decycler_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// DecyclerOscillator wraps the DecyclerOscillator indicator over the Wickra C ABI.
type DecyclerOscillator struct {
	handle *C.struct_DecyclerOscillator
}

// NewDecyclerOscillator constructs a DecyclerOscillator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDecyclerOscillator(fast int, slow int) (*DecyclerOscillator, error) {
	ptr := C.wickra_decycler_oscillator_new(C.uintptr_t(fast), C.uintptr_t(slow))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &DecyclerOscillator{handle: ptr}
	runtime.SetFinalizer(obj, (*DecyclerOscillator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *DecyclerOscillator) WarmupPeriod() int {
	r := int(C.wickra_decycler_oscillator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *DecyclerOscillator) IsReady() bool {
	r := bool(C.wickra_decycler_oscillator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *DecyclerOscillator) Name() string {
	r := C.GoString(C.wickra_decycler_oscillator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *DecyclerOscillator) Update(value float64) float64 {
	r := float64(C.wickra_decycler_oscillator_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *DecyclerOscillator) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_decycler_oscillator_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *DecyclerOscillator) Reset() {
	C.wickra_decycler_oscillator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *DecyclerOscillator) Close() {
	if ind.handle != nil {
		C.wickra_decycler_oscillator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Dema wraps the Dema indicator over the Wickra C ABI.
type Dema struct {
	handle *C.struct_Dema
}

// NewDema constructs a Dema. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDema(period int) (*Dema, error) {
	ptr := C.wickra_dema_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Dema{handle: ptr}
	runtime.SetFinalizer(obj, (*Dema).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Dema) WarmupPeriod() int {
	r := int(C.wickra_dema_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Dema) IsReady() bool {
	r := bool(C.wickra_dema_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Dema) Name() string {
	r := C.GoString(C.wickra_dema_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Dema) Update(value float64) float64 {
	r := float64(C.wickra_dema_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Dema) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_dema_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Dema) Reset() {
	C.wickra_dema_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Dema) Close() {
	if ind.handle != nil {
		C.wickra_dema_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// DemandIndex wraps the DemandIndex indicator over the Wickra C ABI.
type DemandIndex struct {
	handle *C.struct_DemandIndex
}

// NewDemandIndex constructs a DemandIndex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDemandIndex(period int) (*DemandIndex, error) {
	ptr := C.wickra_demand_index_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &DemandIndex{handle: ptr}
	runtime.SetFinalizer(obj, (*DemandIndex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *DemandIndex) WarmupPeriod() int {
	r := int(C.wickra_demand_index_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *DemandIndex) IsReady() bool {
	r := bool(C.wickra_demand_index_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *DemandIndex) Name() string {
	r := C.GoString(C.wickra_demand_index_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *DemandIndex) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_demand_index_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *DemandIndex) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_demand_index_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *DemandIndex) Reset() {
	C.wickra_demand_index_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *DemandIndex) Close() {
	if ind.handle != nil {
		C.wickra_demand_index_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// DemarkPivots wraps the DemarkPivots indicator over the Wickra C ABI.
type DemarkPivots struct {
	handle *C.struct_DemarkPivots
}

// NewDemarkPivots constructs a DemarkPivots. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDemarkPivots() (*DemarkPivots, error) {
	ptr := C.wickra_demark_pivots_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &DemarkPivots{handle: ptr}
	runtime.SetFinalizer(obj, (*DemarkPivots).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *DemarkPivots) WarmupPeriod() int {
	r := int(C.wickra_demark_pivots_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *DemarkPivots) IsReady() bool {
	r := bool(C.wickra_demark_pivots_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *DemarkPivots) Name() string {
	r := C.GoString(C.wickra_demark_pivots_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *DemarkPivots) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (DemarkPivotsOutput, bool) {
	var out C.struct_WickraDemarkPivotsOutput
	ok := bool(C.wickra_demark_pivots_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return DemarkPivotsOutput{}, false
	}
	return DemarkPivotsOutput{float64(out.pp), float64(out.r1), float64(out.s1)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *DemarkPivots) Reset() {
	C.wickra_demark_pivots_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *DemarkPivots) Close() {
	if ind.handle != nil {
		C.wickra_demark_pivots_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// DepthSlope wraps the DepthSlope indicator over the Wickra C ABI.
type DepthSlope struct {
	handle *C.struct_DepthSlope
}

// NewDepthSlope constructs a DepthSlope. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDepthSlope() (*DepthSlope, error) {
	ptr := C.wickra_depth_slope_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &DepthSlope{handle: ptr}
	runtime.SetFinalizer(obj, (*DepthSlope).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *DepthSlope) WarmupPeriod() int {
	r := int(C.wickra_depth_slope_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *DepthSlope) IsReady() bool {
	r := bool(C.wickra_depth_slope_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *DepthSlope) Name() string {
	r := C.GoString(C.wickra_depth_slope_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *DepthSlope) Update(bidPrice []float64, bidSize []float64, askPrice []float64, askSize []float64) float64 {
	if len(bidSize) != len(bidPrice) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(askSize) != len(askPrice) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_depth_slope_update(ind.handle, (*C.double)(unsafe.Pointer(&bidPrice[0])), (*C.double)(unsafe.Pointer(&bidSize[0])), C.uintptr_t(len(bidPrice)), (*C.double)(unsafe.Pointer(&askPrice[0])), (*C.double)(unsafe.Pointer(&askSize[0])), C.uintptr_t(len(askPrice))))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(bidPrice)
	runtime.KeepAlive(bidSize)
	runtime.KeepAlive(askPrice)
	runtime.KeepAlive(askSize)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *DepthSlope) Reset() {
	C.wickra_depth_slope_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *DepthSlope) Close() {
	if ind.handle != nil {
		C.wickra_depth_slope_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// DerivativeOscillator wraps the DerivativeOscillator indicator over the Wickra C ABI.
type DerivativeOscillator struct {
	handle *C.struct_DerivativeOscillator
}

// NewDerivativeOscillator constructs a DerivativeOscillator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDerivativeOscillator(rsiPeriod int, smooth1 int, smooth2 int, signalPeriod int) (*DerivativeOscillator, error) {
	ptr := C.wickra_derivative_oscillator_new(C.uintptr_t(rsiPeriod), C.uintptr_t(smooth1), C.uintptr_t(smooth2), C.uintptr_t(signalPeriod))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &DerivativeOscillator{handle: ptr}
	runtime.SetFinalizer(obj, (*DerivativeOscillator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *DerivativeOscillator) WarmupPeriod() int {
	r := int(C.wickra_derivative_oscillator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *DerivativeOscillator) IsReady() bool {
	r := bool(C.wickra_derivative_oscillator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *DerivativeOscillator) Name() string {
	r := C.GoString(C.wickra_derivative_oscillator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *DerivativeOscillator) Update(value float64) float64 {
	r := float64(C.wickra_derivative_oscillator_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *DerivativeOscillator) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_derivative_oscillator_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *DerivativeOscillator) Reset() {
	C.wickra_derivative_oscillator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *DerivativeOscillator) Close() {
	if ind.handle != nil {
		C.wickra_derivative_oscillator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// DetrendedStdDev wraps the DetrendedStdDev indicator over the Wickra C ABI.
type DetrendedStdDev struct {
	handle *C.struct_DetrendedStdDev
}

// NewDetrendedStdDev constructs a DetrendedStdDev. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDetrendedStdDev(period int) (*DetrendedStdDev, error) {
	ptr := C.wickra_detrended_std_dev_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &DetrendedStdDev{handle: ptr}
	runtime.SetFinalizer(obj, (*DetrendedStdDev).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *DetrendedStdDev) WarmupPeriod() int {
	r := int(C.wickra_detrended_std_dev_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *DetrendedStdDev) IsReady() bool {
	r := bool(C.wickra_detrended_std_dev_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *DetrendedStdDev) Name() string {
	r := C.GoString(C.wickra_detrended_std_dev_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *DetrendedStdDev) Update(value float64) float64 {
	r := float64(C.wickra_detrended_std_dev_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *DetrendedStdDev) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_detrended_std_dev_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *DetrendedStdDev) Reset() {
	C.wickra_detrended_std_dev_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *DetrendedStdDev) Close() {
	if ind.handle != nil {
		C.wickra_detrended_std_dev_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// DisparityIndex wraps the DisparityIndex indicator over the Wickra C ABI.
type DisparityIndex struct {
	handle *C.struct_DisparityIndex
}

// NewDisparityIndex constructs a DisparityIndex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDisparityIndex(period int) (*DisparityIndex, error) {
	ptr := C.wickra_disparity_index_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &DisparityIndex{handle: ptr}
	runtime.SetFinalizer(obj, (*DisparityIndex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *DisparityIndex) WarmupPeriod() int {
	r := int(C.wickra_disparity_index_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *DisparityIndex) IsReady() bool {
	r := bool(C.wickra_disparity_index_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *DisparityIndex) Name() string {
	r := C.GoString(C.wickra_disparity_index_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *DisparityIndex) Update(value float64) float64 {
	r := float64(C.wickra_disparity_index_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *DisparityIndex) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_disparity_index_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *DisparityIndex) Reset() {
	C.wickra_disparity_index_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *DisparityIndex) Close() {
	if ind.handle != nil {
		C.wickra_disparity_index_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// DistanceSsd wraps the DistanceSsd indicator over the Wickra C ABI.
type DistanceSsd struct {
	handle *C.struct_DistanceSsd
}

// NewDistanceSsd constructs a DistanceSsd. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDistanceSsd(period int) (*DistanceSsd, error) {
	ptr := C.wickra_distance_ssd_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &DistanceSsd{handle: ptr}
	runtime.SetFinalizer(obj, (*DistanceSsd).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *DistanceSsd) WarmupPeriod() int {
	r := int(C.wickra_distance_ssd_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *DistanceSsd) IsReady() bool {
	r := bool(C.wickra_distance_ssd_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *DistanceSsd) Name() string {
	r := C.GoString(C.wickra_distance_ssd_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *DistanceSsd) Update(x float64, y float64) float64 {
	r := float64(C.wickra_distance_ssd_update(ind.handle, C.double(x), C.double(y)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *DistanceSsd) Batch(x []float64, y []float64) []float64 {
	n := len(x)
	if len(y) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_distance_ssd_batch(ind.handle, (*C.double)(unsafe.Pointer(&x[0])), (*C.double)(unsafe.Pointer(&y[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(x)
	runtime.KeepAlive(y)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *DistanceSsd) Reset() {
	C.wickra_distance_ssd_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *DistanceSsd) Close() {
	if ind.handle != nil {
		C.wickra_distance_ssd_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Doji wraps the Doji indicator over the Wickra C ABI.
type Doji struct {
	handle *C.struct_Doji
}

// NewDoji constructs a Doji. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDoji() (*Doji, error) {
	ptr := C.wickra_doji_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Doji{handle: ptr}
	runtime.SetFinalizer(obj, (*Doji).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Doji) WarmupPeriod() int {
	r := int(C.wickra_doji_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Doji) IsReady() bool {
	r := bool(C.wickra_doji_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Doji) Name() string {
	r := C.GoString(C.wickra_doji_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Doji) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_doji_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Doji) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_doji_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Doji) Reset() {
	C.wickra_doji_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Doji) Close() {
	if ind.handle != nil {
		C.wickra_doji_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// DojiStar wraps the DojiStar indicator over the Wickra C ABI.
type DojiStar struct {
	handle *C.struct_DojiStar
}

// NewDojiStar constructs a DojiStar. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDojiStar() (*DojiStar, error) {
	ptr := C.wickra_doji_star_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &DojiStar{handle: ptr}
	runtime.SetFinalizer(obj, (*DojiStar).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *DojiStar) WarmupPeriod() int {
	r := int(C.wickra_doji_star_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *DojiStar) IsReady() bool {
	r := bool(C.wickra_doji_star_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *DojiStar) Name() string {
	r := C.GoString(C.wickra_doji_star_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *DojiStar) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_doji_star_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *DojiStar) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_doji_star_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *DojiStar) Reset() {
	C.wickra_doji_star_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *DojiStar) Close() {
	if ind.handle != nil {
		C.wickra_doji_star_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// DollarBars wraps the DollarBars indicator over the Wickra C ABI.
type DollarBars struct {
	handle *C.struct_DollarBars
}

// NewDollarBars constructs a DollarBars. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDollarBars(dollarPerBar float64) (*DollarBars, error) {
	ptr := C.wickra_dollar_bars_new(C.double(dollarPerBar))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &DollarBars{handle: ptr}
	runtime.SetFinalizer(obj, (*DollarBars).Close)
	return obj, nil
}

// Name returns the indicator's canonical name.
func (ind *DollarBars) Name() string {
	r := C.GoString(C.wickra_dollar_bars_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one candle and returns any bars completed by it
// (a single candle may complete several).
func (ind *DollarBars) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) []DollarBar {
	const capacity = 64
	var buf [capacity]C.struct_WickraDollarBar
	n := int(C.wickra_dollar_bars_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &buf[0], C.uintptr_t(capacity)))
	runtime.KeepAlive(ind)
	if n <= 0 {
		return nil
	}
	out := make([]DollarBar, n)
	for i := 0; i < n; i++ {
		out[i] = DollarBar{float64(buf[i].open), float64(buf[i].high), float64(buf[i].low), float64(buf[i].close), float64(buf[i].volume), float64(buf[i].dollar)}
	}
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *DollarBars) Reset() {
	C.wickra_dollar_bars_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *DollarBars) Close() {
	if ind.handle != nil {
		C.wickra_dollar_bars_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Donchian wraps the Donchian indicator over the Wickra C ABI.
type Donchian struct {
	handle *C.struct_Donchian
}

// NewDonchian constructs a Donchian. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDonchian(period int) (*Donchian, error) {
	ptr := C.wickra_donchian_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Donchian{handle: ptr}
	runtime.SetFinalizer(obj, (*Donchian).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Donchian) WarmupPeriod() int {
	r := int(C.wickra_donchian_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Donchian) IsReady() bool {
	r := bool(C.wickra_donchian_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Donchian) Name() string {
	r := C.GoString(C.wickra_donchian_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *Donchian) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (DonchianOutput, bool) {
	var out C.struct_WickraDonchianOutput
	ok := bool(C.wickra_donchian_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return DonchianOutput{}, false
	}
	return DonchianOutput{float64(out.upper), float64(out.middle), float64(out.lower)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Donchian) Reset() {
	C.wickra_donchian_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Donchian) Close() {
	if ind.handle != nil {
		C.wickra_donchian_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// DonchianStop wraps the DonchianStop indicator over the Wickra C ABI.
type DonchianStop struct {
	handle *C.struct_DonchianStop
}

// NewDonchianStop constructs a DonchianStop. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDonchianStop(period int) (*DonchianStop, error) {
	ptr := C.wickra_donchian_stop_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &DonchianStop{handle: ptr}
	runtime.SetFinalizer(obj, (*DonchianStop).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *DonchianStop) WarmupPeriod() int {
	r := int(C.wickra_donchian_stop_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *DonchianStop) IsReady() bool {
	r := bool(C.wickra_donchian_stop_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *DonchianStop) Name() string {
	r := C.GoString(C.wickra_donchian_stop_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *DonchianStop) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (DonchianStopOutput, bool) {
	var out C.struct_WickraDonchianStopOutput
	ok := bool(C.wickra_donchian_stop_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return DonchianStopOutput{}, false
	}
	return DonchianStopOutput{float64(out.stop_long), float64(out.stop_short)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *DonchianStop) Reset() {
	C.wickra_donchian_stop_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *DonchianStop) Close() {
	if ind.handle != nil {
		C.wickra_donchian_stop_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// DoubleBollinger wraps the DoubleBollinger indicator over the Wickra C ABI.
type DoubleBollinger struct {
	handle *C.struct_DoubleBollinger
}

// NewDoubleBollinger constructs a DoubleBollinger. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDoubleBollinger(period int, kInner float64, kOuter float64) (*DoubleBollinger, error) {
	ptr := C.wickra_double_bollinger_new(C.uintptr_t(period), C.double(kInner), C.double(kOuter))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &DoubleBollinger{handle: ptr}
	runtime.SetFinalizer(obj, (*DoubleBollinger).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *DoubleBollinger) WarmupPeriod() int {
	r := int(C.wickra_double_bollinger_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *DoubleBollinger) IsReady() bool {
	r := bool(C.wickra_double_bollinger_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *DoubleBollinger) Name() string {
	r := C.GoString(C.wickra_double_bollinger_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *DoubleBollinger) Update(value float64) (DoubleBollingerOutput, bool) {
	var out C.struct_WickraDoubleBollingerOutput
	ok := bool(C.wickra_double_bollinger_update(ind.handle, C.double(value), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return DoubleBollingerOutput{}, false
	}
	return DoubleBollingerOutput{float64(out.upper_outer), float64(out.upper_inner), float64(out.middle), float64(out.lower_inner), float64(out.lower_outer)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *DoubleBollinger) Reset() {
	C.wickra_double_bollinger_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *DoubleBollinger) Close() {
	if ind.handle != nil {
		C.wickra_double_bollinger_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// DoubleTopBottom wraps the DoubleTopBottom indicator over the Wickra C ABI.
type DoubleTopBottom struct {
	handle *C.struct_DoubleTopBottom
}

// NewDoubleTopBottom constructs a DoubleTopBottom. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDoubleTopBottom() (*DoubleTopBottom, error) {
	ptr := C.wickra_double_top_bottom_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &DoubleTopBottom{handle: ptr}
	runtime.SetFinalizer(obj, (*DoubleTopBottom).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *DoubleTopBottom) WarmupPeriod() int {
	r := int(C.wickra_double_top_bottom_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *DoubleTopBottom) IsReady() bool {
	r := bool(C.wickra_double_top_bottom_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *DoubleTopBottom) Name() string {
	r := C.GoString(C.wickra_double_top_bottom_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *DoubleTopBottom) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_double_top_bottom_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *DoubleTopBottom) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_double_top_bottom_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *DoubleTopBottom) Reset() {
	C.wickra_double_top_bottom_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *DoubleTopBottom) Close() {
	if ind.handle != nil {
		C.wickra_double_top_bottom_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// DownsideGapThreeMethods wraps the DownsideGapThreeMethods indicator over the Wickra C ABI.
type DownsideGapThreeMethods struct {
	handle *C.struct_DownsideGapThreeMethods
}

// NewDownsideGapThreeMethods constructs a DownsideGapThreeMethods. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDownsideGapThreeMethods() (*DownsideGapThreeMethods, error) {
	ptr := C.wickra_downside_gap_three_methods_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &DownsideGapThreeMethods{handle: ptr}
	runtime.SetFinalizer(obj, (*DownsideGapThreeMethods).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *DownsideGapThreeMethods) WarmupPeriod() int {
	r := int(C.wickra_downside_gap_three_methods_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *DownsideGapThreeMethods) IsReady() bool {
	r := bool(C.wickra_downside_gap_three_methods_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *DownsideGapThreeMethods) Name() string {
	r := C.GoString(C.wickra_downside_gap_three_methods_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *DownsideGapThreeMethods) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_downside_gap_three_methods_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *DownsideGapThreeMethods) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_downside_gap_three_methods_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *DownsideGapThreeMethods) Reset() {
	C.wickra_downside_gap_three_methods_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *DownsideGapThreeMethods) Close() {
	if ind.handle != nil {
		C.wickra_downside_gap_three_methods_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Dpo wraps the Dpo indicator over the Wickra C ABI.
type Dpo struct {
	handle *C.struct_Dpo
}

// NewDpo constructs a Dpo. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDpo(period int) (*Dpo, error) {
	ptr := C.wickra_dpo_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Dpo{handle: ptr}
	runtime.SetFinalizer(obj, (*Dpo).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Dpo) WarmupPeriod() int {
	r := int(C.wickra_dpo_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Dpo) IsReady() bool {
	r := bool(C.wickra_dpo_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Dpo) Name() string {
	r := C.GoString(C.wickra_dpo_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Dpo) Update(value float64) float64 {
	r := float64(C.wickra_dpo_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Dpo) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_dpo_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Dpo) Reset() {
	C.wickra_dpo_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Dpo) Close() {
	if ind.handle != nil {
		C.wickra_dpo_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// DragonflyDoji wraps the DragonflyDoji indicator over the Wickra C ABI.
type DragonflyDoji struct {
	handle *C.struct_DragonflyDoji
}

// NewDragonflyDoji constructs a DragonflyDoji. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDragonflyDoji() (*DragonflyDoji, error) {
	ptr := C.wickra_dragonfly_doji_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &DragonflyDoji{handle: ptr}
	runtime.SetFinalizer(obj, (*DragonflyDoji).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *DragonflyDoji) WarmupPeriod() int {
	r := int(C.wickra_dragonfly_doji_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *DragonflyDoji) IsReady() bool {
	r := bool(C.wickra_dragonfly_doji_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *DragonflyDoji) Name() string {
	r := C.GoString(C.wickra_dragonfly_doji_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *DragonflyDoji) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_dragonfly_doji_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *DragonflyDoji) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_dragonfly_doji_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *DragonflyDoji) Reset() {
	C.wickra_dragonfly_doji_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *DragonflyDoji) Close() {
	if ind.handle != nil {
		C.wickra_dragonfly_doji_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// DrawdownDuration wraps the DrawdownDuration indicator over the Wickra C ABI.
type DrawdownDuration struct {
	handle *C.struct_DrawdownDuration
}

// NewDrawdownDuration constructs a DrawdownDuration. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDrawdownDuration() (*DrawdownDuration, error) {
	ptr := C.wickra_drawdown_duration_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &DrawdownDuration{handle: ptr}
	runtime.SetFinalizer(obj, (*DrawdownDuration).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *DrawdownDuration) WarmupPeriod() int {
	r := int(C.wickra_drawdown_duration_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *DrawdownDuration) IsReady() bool {
	r := bool(C.wickra_drawdown_duration_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *DrawdownDuration) Name() string {
	r := C.GoString(C.wickra_drawdown_duration_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *DrawdownDuration) Update(value float64) float64 {
	r := float64(C.wickra_drawdown_duration_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *DrawdownDuration) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_drawdown_duration_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *DrawdownDuration) Reset() {
	C.wickra_drawdown_duration_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *DrawdownDuration) Close() {
	if ind.handle != nil {
		C.wickra_drawdown_duration_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// DumplingTop wraps the DumplingTop indicator over the Wickra C ABI.
type DumplingTop struct {
	handle *C.struct_DumplingTop
}

// NewDumplingTop constructs a DumplingTop. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDumplingTop(period int) (*DumplingTop, error) {
	ptr := C.wickra_dumpling_top_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &DumplingTop{handle: ptr}
	runtime.SetFinalizer(obj, (*DumplingTop).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *DumplingTop) WarmupPeriod() int {
	r := int(C.wickra_dumpling_top_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *DumplingTop) IsReady() bool {
	r := bool(C.wickra_dumpling_top_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *DumplingTop) Name() string {
	r := C.GoString(C.wickra_dumpling_top_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *DumplingTop) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_dumpling_top_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *DumplingTop) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_dumpling_top_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *DumplingTop) Reset() {
	C.wickra_dumpling_top_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *DumplingTop) Close() {
	if ind.handle != nil {
		C.wickra_dumpling_top_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Dx wraps the Dx indicator over the Wickra C ABI.
type Dx struct {
	handle *C.struct_Dx
}

// NewDx constructs a Dx. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDx(period int) (*Dx, error) {
	ptr := C.wickra_dx_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Dx{handle: ptr}
	runtime.SetFinalizer(obj, (*Dx).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Dx) WarmupPeriod() int {
	r := int(C.wickra_dx_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Dx) IsReady() bool {
	r := bool(C.wickra_dx_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Dx) Name() string {
	r := C.GoString(C.wickra_dx_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Dx) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_dx_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Dx) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_dx_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Dx) Reset() {
	C.wickra_dx_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Dx) Close() {
	if ind.handle != nil {
		C.wickra_dx_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// DynamicMomentumIndex wraps the DynamicMomentumIndex indicator over the Wickra C ABI.
type DynamicMomentumIndex struct {
	handle *C.struct_DynamicMomentumIndex
}

// NewDynamicMomentumIndex constructs a DynamicMomentumIndex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewDynamicMomentumIndex(period int) (*DynamicMomentumIndex, error) {
	ptr := C.wickra_dynamic_momentum_index_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &DynamicMomentumIndex{handle: ptr}
	runtime.SetFinalizer(obj, (*DynamicMomentumIndex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *DynamicMomentumIndex) WarmupPeriod() int {
	r := int(C.wickra_dynamic_momentum_index_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *DynamicMomentumIndex) IsReady() bool {
	r := bool(C.wickra_dynamic_momentum_index_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *DynamicMomentumIndex) Name() string {
	r := C.GoString(C.wickra_dynamic_momentum_index_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *DynamicMomentumIndex) Update(value float64) float64 {
	r := float64(C.wickra_dynamic_momentum_index_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *DynamicMomentumIndex) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_dynamic_momentum_index_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *DynamicMomentumIndex) Reset() {
	C.wickra_dynamic_momentum_index_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *DynamicMomentumIndex) Close() {
	if ind.handle != nil {
		C.wickra_dynamic_momentum_index_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// EaseOfMovement wraps the EaseOfMovement indicator over the Wickra C ABI.
type EaseOfMovement struct {
	handle *C.struct_EaseOfMovement
}

// NewEaseOfMovement constructs a EaseOfMovement. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewEaseOfMovement(period int) (*EaseOfMovement, error) {
	ptr := C.wickra_ease_of_movement_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &EaseOfMovement{handle: ptr}
	runtime.SetFinalizer(obj, (*EaseOfMovement).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *EaseOfMovement) WarmupPeriod() int {
	r := int(C.wickra_ease_of_movement_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *EaseOfMovement) IsReady() bool {
	r := bool(C.wickra_ease_of_movement_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *EaseOfMovement) Name() string {
	r := C.GoString(C.wickra_ease_of_movement_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *EaseOfMovement) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_ease_of_movement_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *EaseOfMovement) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_ease_of_movement_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *EaseOfMovement) Reset() {
	C.wickra_ease_of_movement_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *EaseOfMovement) Close() {
	if ind.handle != nil {
		C.wickra_ease_of_movement_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// EffectiveSpread wraps the EffectiveSpread indicator over the Wickra C ABI.
type EffectiveSpread struct {
	handle *C.struct_EffectiveSpread
}

// NewEffectiveSpread constructs a EffectiveSpread. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewEffectiveSpread() (*EffectiveSpread, error) {
	ptr := C.wickra_effective_spread_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &EffectiveSpread{handle: ptr}
	runtime.SetFinalizer(obj, (*EffectiveSpread).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *EffectiveSpread) WarmupPeriod() int {
	r := int(C.wickra_effective_spread_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *EffectiveSpread) IsReady() bool {
	r := bool(C.wickra_effective_spread_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *EffectiveSpread) Name() string {
	r := C.GoString(C.wickra_effective_spread_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *EffectiveSpread) Update(price float64, size float64, isBuy bool, timestamp int64, mid float64) float64 {
	r := float64(C.wickra_effective_spread_update(ind.handle, C.double(price), C.double(size), C.bool(isBuy), C.int64_t(timestamp), C.double(mid)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *EffectiveSpread) Reset() {
	C.wickra_effective_spread_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *EffectiveSpread) Close() {
	if ind.handle != nil {
		C.wickra_effective_spread_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// EhlersStochastic wraps the EhlersStochastic indicator over the Wickra C ABI.
type EhlersStochastic struct {
	handle *C.struct_EhlersStochastic
}

// NewEhlersStochastic constructs a EhlersStochastic. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewEhlersStochastic(period int) (*EhlersStochastic, error) {
	ptr := C.wickra_ehlers_stochastic_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &EhlersStochastic{handle: ptr}
	runtime.SetFinalizer(obj, (*EhlersStochastic).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *EhlersStochastic) WarmupPeriod() int {
	r := int(C.wickra_ehlers_stochastic_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *EhlersStochastic) IsReady() bool {
	r := bool(C.wickra_ehlers_stochastic_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *EhlersStochastic) Name() string {
	r := C.GoString(C.wickra_ehlers_stochastic_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *EhlersStochastic) Update(value float64) float64 {
	r := float64(C.wickra_ehlers_stochastic_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *EhlersStochastic) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_ehlers_stochastic_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *EhlersStochastic) Reset() {
	C.wickra_ehlers_stochastic_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *EhlersStochastic) Close() {
	if ind.handle != nil {
		C.wickra_ehlers_stochastic_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Ehma wraps the Ehma indicator over the Wickra C ABI.
type Ehma struct {
	handle *C.struct_Ehma
}

// NewEhma constructs a Ehma. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewEhma(period int) (*Ehma, error) {
	ptr := C.wickra_ehma_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Ehma{handle: ptr}
	runtime.SetFinalizer(obj, (*Ehma).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Ehma) WarmupPeriod() int {
	r := int(C.wickra_ehma_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Ehma) IsReady() bool {
	r := bool(C.wickra_ehma_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Ehma) Name() string {
	r := C.GoString(C.wickra_ehma_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Ehma) Update(value float64) float64 {
	r := float64(C.wickra_ehma_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Ehma) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_ehma_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Ehma) Reset() {
	C.wickra_ehma_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Ehma) Close() {
	if ind.handle != nil {
		C.wickra_ehma_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ElderImpulse wraps the ElderImpulse indicator over the Wickra C ABI.
type ElderImpulse struct {
	handle *C.struct_ElderImpulse
}

// NewElderImpulse constructs a ElderImpulse. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewElderImpulse(emaPeriod int, macdFast int, macdSlow int, macdSignal int) (*ElderImpulse, error) {
	ptr := C.wickra_elder_impulse_new(C.uintptr_t(emaPeriod), C.uintptr_t(macdFast), C.uintptr_t(macdSlow), C.uintptr_t(macdSignal))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ElderImpulse{handle: ptr}
	runtime.SetFinalizer(obj, (*ElderImpulse).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ElderImpulse) WarmupPeriod() int {
	r := int(C.wickra_elder_impulse_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ElderImpulse) IsReady() bool {
	r := bool(C.wickra_elder_impulse_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ElderImpulse) Name() string {
	r := C.GoString(C.wickra_elder_impulse_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ElderImpulse) Update(value float64) float64 {
	r := float64(C.wickra_elder_impulse_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ElderImpulse) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_elder_impulse_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ElderImpulse) Reset() {
	C.wickra_elder_impulse_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ElderImpulse) Close() {
	if ind.handle != nil {
		C.wickra_elder_impulse_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ElderRay wraps the ElderRay indicator over the Wickra C ABI.
type ElderRay struct {
	handle *C.struct_ElderRay
}

// NewElderRay constructs a ElderRay. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewElderRay(period int) (*ElderRay, error) {
	ptr := C.wickra_elder_ray_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ElderRay{handle: ptr}
	runtime.SetFinalizer(obj, (*ElderRay).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ElderRay) WarmupPeriod() int {
	r := int(C.wickra_elder_ray_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ElderRay) IsReady() bool {
	r := bool(C.wickra_elder_ray_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ElderRay) Name() string {
	r := C.GoString(C.wickra_elder_ray_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *ElderRay) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (ElderRayOutput, bool) {
	var out C.struct_WickraElderRayOutput
	ok := bool(C.wickra_elder_ray_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return ElderRayOutput{}, false
	}
	return ElderRayOutput{float64(out.bull_power), float64(out.bear_power)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ElderRay) Reset() {
	C.wickra_elder_ray_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ElderRay) Close() {
	if ind.handle != nil {
		C.wickra_elder_ray_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ElderSafeZone wraps the ElderSafeZone indicator over the Wickra C ABI.
type ElderSafeZone struct {
	handle *C.struct_ElderSafeZone
}

// NewElderSafeZone constructs a ElderSafeZone. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewElderSafeZone(period int, coeff float64) (*ElderSafeZone, error) {
	ptr := C.wickra_elder_safe_zone_new(C.uintptr_t(period), C.double(coeff))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ElderSafeZone{handle: ptr}
	runtime.SetFinalizer(obj, (*ElderSafeZone).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ElderSafeZone) WarmupPeriod() int {
	r := int(C.wickra_elder_safe_zone_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ElderSafeZone) IsReady() bool {
	r := bool(C.wickra_elder_safe_zone_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ElderSafeZone) Name() string {
	r := C.GoString(C.wickra_elder_safe_zone_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *ElderSafeZone) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (ElderSafeZoneOutput, bool) {
	var out C.struct_WickraElderSafeZoneOutput
	ok := bool(C.wickra_elder_safe_zone_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return ElderSafeZoneOutput{}, false
	}
	return ElderSafeZoneOutput{float64(out.value), float64(out.direction)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ElderSafeZone) Reset() {
	C.wickra_elder_safe_zone_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ElderSafeZone) Close() {
	if ind.handle != nil {
		C.wickra_elder_safe_zone_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Ema wraps the Ema indicator over the Wickra C ABI.
type Ema struct {
	handle *C.struct_Ema
}

// NewEma constructs a Ema. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewEma(period int) (*Ema, error) {
	ptr := C.wickra_ema_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Ema{handle: ptr}
	runtime.SetFinalizer(obj, (*Ema).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Ema) WarmupPeriod() int {
	r := int(C.wickra_ema_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Ema) IsReady() bool {
	r := bool(C.wickra_ema_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Ema) Name() string {
	r := C.GoString(C.wickra_ema_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Ema) Update(value float64) float64 {
	r := float64(C.wickra_ema_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Ema) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_ema_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Ema) Reset() {
	C.wickra_ema_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Ema) Close() {
	if ind.handle != nil {
		C.wickra_ema_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// EmpiricalModeDecomposition wraps the EmpiricalModeDecomposition indicator over the Wickra C ABI.
type EmpiricalModeDecomposition struct {
	handle *C.struct_EmpiricalModeDecomposition
}

// NewEmpiricalModeDecomposition constructs a EmpiricalModeDecomposition. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewEmpiricalModeDecomposition(period int, fraction float64) (*EmpiricalModeDecomposition, error) {
	ptr := C.wickra_empirical_mode_decomposition_new(C.uintptr_t(period), C.double(fraction))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &EmpiricalModeDecomposition{handle: ptr}
	runtime.SetFinalizer(obj, (*EmpiricalModeDecomposition).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *EmpiricalModeDecomposition) WarmupPeriod() int {
	r := int(C.wickra_empirical_mode_decomposition_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *EmpiricalModeDecomposition) IsReady() bool {
	r := bool(C.wickra_empirical_mode_decomposition_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *EmpiricalModeDecomposition) Name() string {
	r := C.GoString(C.wickra_empirical_mode_decomposition_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *EmpiricalModeDecomposition) Update(value float64) float64 {
	r := float64(C.wickra_empirical_mode_decomposition_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *EmpiricalModeDecomposition) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_empirical_mode_decomposition_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *EmpiricalModeDecomposition) Reset() {
	C.wickra_empirical_mode_decomposition_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *EmpiricalModeDecomposition) Close() {
	if ind.handle != nil {
		C.wickra_empirical_mode_decomposition_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Engulfing wraps the Engulfing indicator over the Wickra C ABI.
type Engulfing struct {
	handle *C.struct_Engulfing
}

// NewEngulfing constructs a Engulfing. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewEngulfing() (*Engulfing, error) {
	ptr := C.wickra_engulfing_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Engulfing{handle: ptr}
	runtime.SetFinalizer(obj, (*Engulfing).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Engulfing) WarmupPeriod() int {
	r := int(C.wickra_engulfing_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Engulfing) IsReady() bool {
	r := bool(C.wickra_engulfing_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Engulfing) Name() string {
	r := C.GoString(C.wickra_engulfing_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Engulfing) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_engulfing_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Engulfing) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_engulfing_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Engulfing) Reset() {
	C.wickra_engulfing_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Engulfing) Close() {
	if ind.handle != nil {
		C.wickra_engulfing_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Equivolume wraps the Equivolume indicator over the Wickra C ABI.
type Equivolume struct {
	handle *C.struct_Equivolume
}

// NewEquivolume constructs a Equivolume. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewEquivolume(period int) (*Equivolume, error) {
	ptr := C.wickra_equivolume_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Equivolume{handle: ptr}
	runtime.SetFinalizer(obj, (*Equivolume).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Equivolume) WarmupPeriod() int {
	r := int(C.wickra_equivolume_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Equivolume) IsReady() bool {
	r := bool(C.wickra_equivolume_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Equivolume) Name() string {
	r := C.GoString(C.wickra_equivolume_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *Equivolume) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (EquivolumeOutput, bool) {
	var out C.struct_WickraEquivolumeOutput
	ok := bool(C.wickra_equivolume_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return EquivolumeOutput{}, false
	}
	return EquivolumeOutput{float64(out.height), float64(out.width)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Equivolume) Reset() {
	C.wickra_equivolume_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Equivolume) Close() {
	if ind.handle != nil {
		C.wickra_equivolume_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// EstimatedLeverageRatio wraps the EstimatedLeverageRatio indicator over the Wickra C ABI.
type EstimatedLeverageRatio struct {
	handle *C.struct_EstimatedLeverageRatio
}

// NewEstimatedLeverageRatio constructs a EstimatedLeverageRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewEstimatedLeverageRatio() (*EstimatedLeverageRatio, error) {
	ptr := C.wickra_estimated_leverage_ratio_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &EstimatedLeverageRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*EstimatedLeverageRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *EstimatedLeverageRatio) WarmupPeriod() int {
	r := int(C.wickra_estimated_leverage_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *EstimatedLeverageRatio) IsReady() bool {
	r := bool(C.wickra_estimated_leverage_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *EstimatedLeverageRatio) Name() string {
	r := C.GoString(C.wickra_estimated_leverage_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *EstimatedLeverageRatio) Update(fundingRate float64, markPrice float64, indexPrice float64, futuresPrice float64, openInterest float64, longSize float64, shortSize float64, takerBuyVolume float64, takerSellVolume float64, longLiquidation float64, shortLiquidation float64, timestamp int64) float64 {
	r := float64(C.wickra_estimated_leverage_ratio_update(ind.handle, C.double(fundingRate), C.double(markPrice), C.double(indexPrice), C.double(futuresPrice), C.double(openInterest), C.double(longSize), C.double(shortSize), C.double(takerBuyVolume), C.double(takerSellVolume), C.double(longLiquidation), C.double(shortLiquidation), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *EstimatedLeverageRatio) Reset() {
	C.wickra_estimated_leverage_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *EstimatedLeverageRatio) Close() {
	if ind.handle != nil {
		C.wickra_estimated_leverage_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// EvenBetterSinewave wraps the EvenBetterSinewave indicator over the Wickra C ABI.
type EvenBetterSinewave struct {
	handle *C.struct_EvenBetterSinewave
}

// NewEvenBetterSinewave constructs a EvenBetterSinewave. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewEvenBetterSinewave(hpPeriod int, ssfLength int) (*EvenBetterSinewave, error) {
	ptr := C.wickra_even_better_sinewave_new(C.uintptr_t(hpPeriod), C.uintptr_t(ssfLength))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &EvenBetterSinewave{handle: ptr}
	runtime.SetFinalizer(obj, (*EvenBetterSinewave).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *EvenBetterSinewave) WarmupPeriod() int {
	r := int(C.wickra_even_better_sinewave_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *EvenBetterSinewave) IsReady() bool {
	r := bool(C.wickra_even_better_sinewave_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *EvenBetterSinewave) Name() string {
	r := C.GoString(C.wickra_even_better_sinewave_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *EvenBetterSinewave) Update(value float64) float64 {
	r := float64(C.wickra_even_better_sinewave_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *EvenBetterSinewave) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_even_better_sinewave_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *EvenBetterSinewave) Reset() {
	C.wickra_even_better_sinewave_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *EvenBetterSinewave) Close() {
	if ind.handle != nil {
		C.wickra_even_better_sinewave_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// EveningDojiStar wraps the EveningDojiStar indicator over the Wickra C ABI.
type EveningDojiStar struct {
	handle *C.struct_EveningDojiStar
}

// NewEveningDojiStar constructs a EveningDojiStar. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewEveningDojiStar() (*EveningDojiStar, error) {
	ptr := C.wickra_evening_doji_star_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &EveningDojiStar{handle: ptr}
	runtime.SetFinalizer(obj, (*EveningDojiStar).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *EveningDojiStar) WarmupPeriod() int {
	r := int(C.wickra_evening_doji_star_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *EveningDojiStar) IsReady() bool {
	r := bool(C.wickra_evening_doji_star_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *EveningDojiStar) Name() string {
	r := C.GoString(C.wickra_evening_doji_star_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *EveningDojiStar) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_evening_doji_star_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *EveningDojiStar) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_evening_doji_star_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *EveningDojiStar) Reset() {
	C.wickra_evening_doji_star_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *EveningDojiStar) Close() {
	if ind.handle != nil {
		C.wickra_evening_doji_star_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Evwma wraps the Evwma indicator over the Wickra C ABI.
type Evwma struct {
	handle *C.struct_Evwma
}

// NewEvwma constructs a Evwma. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewEvwma(period int) (*Evwma, error) {
	ptr := C.wickra_evwma_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Evwma{handle: ptr}
	runtime.SetFinalizer(obj, (*Evwma).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Evwma) WarmupPeriod() int {
	r := int(C.wickra_evwma_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Evwma) IsReady() bool {
	r := bool(C.wickra_evwma_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Evwma) Name() string {
	r := C.GoString(C.wickra_evwma_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Evwma) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_evwma_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Evwma) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_evwma_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Evwma) Reset() {
	C.wickra_evwma_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Evwma) Close() {
	if ind.handle != nil {
		C.wickra_evwma_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// EwmaVolatility wraps the EwmaVolatility indicator over the Wickra C ABI.
type EwmaVolatility struct {
	handle *C.struct_EwmaVolatility
}

// NewEwmaVolatility constructs a EwmaVolatility. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewEwmaVolatility(lambda float64) (*EwmaVolatility, error) {
	ptr := C.wickra_ewma_volatility_new(C.double(lambda))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &EwmaVolatility{handle: ptr}
	runtime.SetFinalizer(obj, (*EwmaVolatility).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *EwmaVolatility) WarmupPeriod() int {
	r := int(C.wickra_ewma_volatility_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *EwmaVolatility) IsReady() bool {
	r := bool(C.wickra_ewma_volatility_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *EwmaVolatility) Name() string {
	r := C.GoString(C.wickra_ewma_volatility_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *EwmaVolatility) Update(value float64) float64 {
	r := float64(C.wickra_ewma_volatility_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *EwmaVolatility) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_ewma_volatility_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *EwmaVolatility) Reset() {
	C.wickra_ewma_volatility_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *EwmaVolatility) Close() {
	if ind.handle != nil {
		C.wickra_ewma_volatility_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Expectancy wraps the Expectancy indicator over the Wickra C ABI.
type Expectancy struct {
	handle *C.struct_Expectancy
}

// NewExpectancy constructs a Expectancy. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewExpectancy(period int) (*Expectancy, error) {
	ptr := C.wickra_expectancy_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Expectancy{handle: ptr}
	runtime.SetFinalizer(obj, (*Expectancy).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Expectancy) WarmupPeriod() int {
	r := int(C.wickra_expectancy_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Expectancy) IsReady() bool {
	r := bool(C.wickra_expectancy_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Expectancy) Name() string {
	r := C.GoString(C.wickra_expectancy_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Expectancy) Update(value float64) float64 {
	r := float64(C.wickra_expectancy_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Expectancy) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_expectancy_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Expectancy) Reset() {
	C.wickra_expectancy_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Expectancy) Close() {
	if ind.handle != nil {
		C.wickra_expectancy_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FallingThreeMethods wraps the FallingThreeMethods indicator over the Wickra C ABI.
type FallingThreeMethods struct {
	handle *C.struct_FallingThreeMethods
}

// NewFallingThreeMethods constructs a FallingThreeMethods. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFallingThreeMethods() (*FallingThreeMethods, error) {
	ptr := C.wickra_falling_three_methods_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FallingThreeMethods{handle: ptr}
	runtime.SetFinalizer(obj, (*FallingThreeMethods).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FallingThreeMethods) WarmupPeriod() int {
	r := int(C.wickra_falling_three_methods_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FallingThreeMethods) IsReady() bool {
	r := bool(C.wickra_falling_three_methods_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FallingThreeMethods) Name() string {
	r := C.GoString(C.wickra_falling_three_methods_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *FallingThreeMethods) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_falling_three_methods_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *FallingThreeMethods) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_falling_three_methods_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FallingThreeMethods) Reset() {
	C.wickra_falling_three_methods_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FallingThreeMethods) Close() {
	if ind.handle != nil {
		C.wickra_falling_three_methods_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Fama wraps the Fama indicator over the Wickra C ABI.
type Fama struct {
	handle *C.struct_Fama
}

// NewFama constructs a Fama. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFama(fastLimit float64, slowLimit float64) (*Fama, error) {
	ptr := C.wickra_fama_new(C.double(fastLimit), C.double(slowLimit))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Fama{handle: ptr}
	runtime.SetFinalizer(obj, (*Fama).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Fama) WarmupPeriod() int {
	r := int(C.wickra_fama_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Fama) IsReady() bool {
	r := bool(C.wickra_fama_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Fama) Name() string {
	r := C.GoString(C.wickra_fama_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Fama) Update(value float64) float64 {
	r := float64(C.wickra_fama_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Fama) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_fama_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Fama) Reset() {
	C.wickra_fama_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Fama) Close() {
	if ind.handle != nil {
		C.wickra_fama_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FibArcs wraps the FibArcs indicator over the Wickra C ABI.
type FibArcs struct {
	handle *C.struct_FibArcs
}

// NewFibArcs constructs a FibArcs. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFibArcs() (*FibArcs, error) {
	ptr := C.wickra_fib_arcs_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FibArcs{handle: ptr}
	runtime.SetFinalizer(obj, (*FibArcs).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FibArcs) WarmupPeriod() int {
	r := int(C.wickra_fib_arcs_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FibArcs) IsReady() bool {
	r := bool(C.wickra_fib_arcs_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FibArcs) Name() string {
	r := C.GoString(C.wickra_fib_arcs_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *FibArcs) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (FibArcsOutput, bool) {
	var out C.struct_WickraFibArcsOutput
	ok := bool(C.wickra_fib_arcs_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return FibArcsOutput{}, false
	}
	return FibArcsOutput{float64(out.arc_382), float64(out.arc_500), float64(out.arc_618)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FibArcs) Reset() {
	C.wickra_fib_arcs_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FibArcs) Close() {
	if ind.handle != nil {
		C.wickra_fib_arcs_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FibChannel wraps the FibChannel indicator over the Wickra C ABI.
type FibChannel struct {
	handle *C.struct_FibChannel
}

// NewFibChannel constructs a FibChannel. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFibChannel() (*FibChannel, error) {
	ptr := C.wickra_fib_channel_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FibChannel{handle: ptr}
	runtime.SetFinalizer(obj, (*FibChannel).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FibChannel) WarmupPeriod() int {
	r := int(C.wickra_fib_channel_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FibChannel) IsReady() bool {
	r := bool(C.wickra_fib_channel_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FibChannel) Name() string {
	r := C.GoString(C.wickra_fib_channel_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *FibChannel) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (FibChannelOutput, bool) {
	var out C.struct_WickraFibChannelOutput
	ok := bool(C.wickra_fib_channel_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return FibChannelOutput{}, false
	}
	return FibChannelOutput{float64(out.base), float64(out.level_618), float64(out.level_1000), float64(out.level_1618)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FibChannel) Reset() {
	C.wickra_fib_channel_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FibChannel) Close() {
	if ind.handle != nil {
		C.wickra_fib_channel_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FibConfluence wraps the FibConfluence indicator over the Wickra C ABI.
type FibConfluence struct {
	handle *C.struct_FibConfluence
}

// NewFibConfluence constructs a FibConfluence. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFibConfluence() (*FibConfluence, error) {
	ptr := C.wickra_fib_confluence_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FibConfluence{handle: ptr}
	runtime.SetFinalizer(obj, (*FibConfluence).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FibConfluence) WarmupPeriod() int {
	r := int(C.wickra_fib_confluence_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FibConfluence) IsReady() bool {
	r := bool(C.wickra_fib_confluence_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FibConfluence) Name() string {
	r := C.GoString(C.wickra_fib_confluence_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *FibConfluence) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (FibConfluenceOutput, bool) {
	var out C.struct_WickraFibConfluenceOutput
	ok := bool(C.wickra_fib_confluence_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return FibConfluenceOutput{}, false
	}
	return FibConfluenceOutput{float64(out.price), float64(out.strength)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FibConfluence) Reset() {
	C.wickra_fib_confluence_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FibConfluence) Close() {
	if ind.handle != nil {
		C.wickra_fib_confluence_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FibExtension wraps the FibExtension indicator over the Wickra C ABI.
type FibExtension struct {
	handle *C.struct_FibExtension
}

// NewFibExtension constructs a FibExtension. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFibExtension() (*FibExtension, error) {
	ptr := C.wickra_fib_extension_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FibExtension{handle: ptr}
	runtime.SetFinalizer(obj, (*FibExtension).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FibExtension) WarmupPeriod() int {
	r := int(C.wickra_fib_extension_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FibExtension) IsReady() bool {
	r := bool(C.wickra_fib_extension_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FibExtension) Name() string {
	r := C.GoString(C.wickra_fib_extension_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *FibExtension) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (FibExtensionOutput, bool) {
	var out C.struct_WickraFibExtensionOutput
	ok := bool(C.wickra_fib_extension_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return FibExtensionOutput{}, false
	}
	return FibExtensionOutput{float64(out.level_1272), float64(out.level_1414), float64(out.level_1618), float64(out.level_2000), float64(out.level_2618)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FibExtension) Reset() {
	C.wickra_fib_extension_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FibExtension) Close() {
	if ind.handle != nil {
		C.wickra_fib_extension_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FibFan wraps the FibFan indicator over the Wickra C ABI.
type FibFan struct {
	handle *C.struct_FibFan
}

// NewFibFan constructs a FibFan. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFibFan() (*FibFan, error) {
	ptr := C.wickra_fib_fan_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FibFan{handle: ptr}
	runtime.SetFinalizer(obj, (*FibFan).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FibFan) WarmupPeriod() int {
	r := int(C.wickra_fib_fan_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FibFan) IsReady() bool {
	r := bool(C.wickra_fib_fan_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FibFan) Name() string {
	r := C.GoString(C.wickra_fib_fan_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *FibFan) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (FibFanOutput, bool) {
	var out C.struct_WickraFibFanOutput
	ok := bool(C.wickra_fib_fan_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return FibFanOutput{}, false
	}
	return FibFanOutput{float64(out.fan_382), float64(out.fan_500), float64(out.fan_618)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FibFan) Reset() {
	C.wickra_fib_fan_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FibFan) Close() {
	if ind.handle != nil {
		C.wickra_fib_fan_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FibProjection wraps the FibProjection indicator over the Wickra C ABI.
type FibProjection struct {
	handle *C.struct_FibProjection
}

// NewFibProjection constructs a FibProjection. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFibProjection() (*FibProjection, error) {
	ptr := C.wickra_fib_projection_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FibProjection{handle: ptr}
	runtime.SetFinalizer(obj, (*FibProjection).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FibProjection) WarmupPeriod() int {
	r := int(C.wickra_fib_projection_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FibProjection) IsReady() bool {
	r := bool(C.wickra_fib_projection_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FibProjection) Name() string {
	r := C.GoString(C.wickra_fib_projection_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *FibProjection) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (FibProjectionOutput, bool) {
	var out C.struct_WickraFibProjectionOutput
	ok := bool(C.wickra_fib_projection_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return FibProjectionOutput{}, false
	}
	return FibProjectionOutput{float64(out.level_618), float64(out.level_1000), float64(out.level_1618), float64(out.level_2618)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FibProjection) Reset() {
	C.wickra_fib_projection_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FibProjection) Close() {
	if ind.handle != nil {
		C.wickra_fib_projection_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FibRetracement wraps the FibRetracement indicator over the Wickra C ABI.
type FibRetracement struct {
	handle *C.struct_FibRetracement
}

// NewFibRetracement constructs a FibRetracement. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFibRetracement() (*FibRetracement, error) {
	ptr := C.wickra_fib_retracement_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FibRetracement{handle: ptr}
	runtime.SetFinalizer(obj, (*FibRetracement).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FibRetracement) WarmupPeriod() int {
	r := int(C.wickra_fib_retracement_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FibRetracement) IsReady() bool {
	r := bool(C.wickra_fib_retracement_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FibRetracement) Name() string {
	r := C.GoString(C.wickra_fib_retracement_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *FibRetracement) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (FibRetracementOutput, bool) {
	var out C.struct_WickraFibRetracementOutput
	ok := bool(C.wickra_fib_retracement_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return FibRetracementOutput{}, false
	}
	return FibRetracementOutput{float64(out.level_0), float64(out.level_236), float64(out.level_382), float64(out.level_500), float64(out.level_618), float64(out.level_786), float64(out.level_1000)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FibRetracement) Reset() {
	C.wickra_fib_retracement_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FibRetracement) Close() {
	if ind.handle != nil {
		C.wickra_fib_retracement_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FibTimeZones wraps the FibTimeZones indicator over the Wickra C ABI.
type FibTimeZones struct {
	handle *C.struct_FibTimeZones
}

// NewFibTimeZones constructs a FibTimeZones. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFibTimeZones() (*FibTimeZones, error) {
	ptr := C.wickra_fib_time_zones_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FibTimeZones{handle: ptr}
	runtime.SetFinalizer(obj, (*FibTimeZones).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FibTimeZones) WarmupPeriod() int {
	r := int(C.wickra_fib_time_zones_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FibTimeZones) IsReady() bool {
	r := bool(C.wickra_fib_time_zones_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FibTimeZones) Name() string {
	r := C.GoString(C.wickra_fib_time_zones_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *FibTimeZones) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (FibTimeZonesOutput, bool) {
	var out C.struct_WickraFibTimeZonesOutput
	ok := bool(C.wickra_fib_time_zones_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return FibTimeZonesOutput{}, false
	}
	return FibTimeZonesOutput{float64(out.on_zone), float64(out.bars_to_next)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FibTimeZones) Reset() {
	C.wickra_fib_time_zones_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FibTimeZones) Close() {
	if ind.handle != nil {
		C.wickra_fib_time_zones_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FibonacciPivots wraps the FibonacciPivots indicator over the Wickra C ABI.
type FibonacciPivots struct {
	handle *C.struct_FibonacciPivots
}

// NewFibonacciPivots constructs a FibonacciPivots. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFibonacciPivots() (*FibonacciPivots, error) {
	ptr := C.wickra_fibonacci_pivots_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FibonacciPivots{handle: ptr}
	runtime.SetFinalizer(obj, (*FibonacciPivots).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FibonacciPivots) WarmupPeriod() int {
	r := int(C.wickra_fibonacci_pivots_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FibonacciPivots) IsReady() bool {
	r := bool(C.wickra_fibonacci_pivots_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FibonacciPivots) Name() string {
	r := C.GoString(C.wickra_fibonacci_pivots_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *FibonacciPivots) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (FibonacciPivotsOutput, bool) {
	var out C.struct_WickraFibonacciPivotsOutput
	ok := bool(C.wickra_fibonacci_pivots_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return FibonacciPivotsOutput{}, false
	}
	return FibonacciPivotsOutput{float64(out.pp), float64(out.r1), float64(out.r2), float64(out.r3), float64(out.s1), float64(out.s2), float64(out.s3)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FibonacciPivots) Reset() {
	C.wickra_fibonacci_pivots_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FibonacciPivots) Close() {
	if ind.handle != nil {
		C.wickra_fibonacci_pivots_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FisherRsi wraps the FisherRsi indicator over the Wickra C ABI.
type FisherRsi struct {
	handle *C.struct_FisherRsi
}

// NewFisherRsi constructs a FisherRsi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFisherRsi(period int) (*FisherRsi, error) {
	ptr := C.wickra_fisher_rsi_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FisherRsi{handle: ptr}
	runtime.SetFinalizer(obj, (*FisherRsi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FisherRsi) WarmupPeriod() int {
	r := int(C.wickra_fisher_rsi_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FisherRsi) IsReady() bool {
	r := bool(C.wickra_fisher_rsi_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FisherRsi) Name() string {
	r := C.GoString(C.wickra_fisher_rsi_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *FisherRsi) Update(value float64) float64 {
	r := float64(C.wickra_fisher_rsi_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *FisherRsi) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_fisher_rsi_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FisherRsi) Reset() {
	C.wickra_fisher_rsi_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FisherRsi) Close() {
	if ind.handle != nil {
		C.wickra_fisher_rsi_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FisherTransform wraps the FisherTransform indicator over the Wickra C ABI.
type FisherTransform struct {
	handle *C.struct_FisherTransform
}

// NewFisherTransform constructs a FisherTransform. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFisherTransform(period int) (*FisherTransform, error) {
	ptr := C.wickra_fisher_transform_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FisherTransform{handle: ptr}
	runtime.SetFinalizer(obj, (*FisherTransform).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FisherTransform) WarmupPeriod() int {
	r := int(C.wickra_fisher_transform_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FisherTransform) IsReady() bool {
	r := bool(C.wickra_fisher_transform_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FisherTransform) Name() string {
	r := C.GoString(C.wickra_fisher_transform_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *FisherTransform) Update(value float64) float64 {
	r := float64(C.wickra_fisher_transform_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *FisherTransform) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_fisher_transform_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FisherTransform) Reset() {
	C.wickra_fisher_transform_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FisherTransform) Close() {
	if ind.handle != nil {
		C.wickra_fisher_transform_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FlagPennant wraps the FlagPennant indicator over the Wickra C ABI.
type FlagPennant struct {
	handle *C.struct_FlagPennant
}

// NewFlagPennant constructs a FlagPennant. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFlagPennant() (*FlagPennant, error) {
	ptr := C.wickra_flag_pennant_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FlagPennant{handle: ptr}
	runtime.SetFinalizer(obj, (*FlagPennant).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FlagPennant) WarmupPeriod() int {
	r := int(C.wickra_flag_pennant_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FlagPennant) IsReady() bool {
	r := bool(C.wickra_flag_pennant_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FlagPennant) Name() string {
	r := C.GoString(C.wickra_flag_pennant_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *FlagPennant) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_flag_pennant_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *FlagPennant) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_flag_pennant_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FlagPennant) Reset() {
	C.wickra_flag_pennant_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FlagPennant) Close() {
	if ind.handle != nil {
		C.wickra_flag_pennant_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Footprint wraps the Footprint indicator over the Wickra C ABI.
type Footprint struct {
	handle *C.struct_Footprint
}

// NewFootprint constructs a Footprint. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFootprint(tickSize float64) (*Footprint, error) {
	ptr := C.wickra_footprint_new(C.double(tickSize))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Footprint{handle: ptr}
	runtime.SetFinalizer(obj, (*Footprint).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Footprint) WarmupPeriod() int {
	r := int(C.wickra_footprint_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Footprint) IsReady() bool {
	r := bool(C.wickra_footprint_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Footprint) Name() string {
	r := C.GoString(C.wickra_footprint_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one candle and returns any bars completed by it
// (a single candle may complete several).
func (ind *Footprint) Update(price float64, size float64, isBuy bool, timestamp int64) []FootprintLevel {
	const capacity = 64
	var buf [capacity]C.struct_WickraFootprintLevel
	n := int(C.wickra_footprint_update(ind.handle, C.double(price), C.double(size), C.bool(isBuy), C.int64_t(timestamp), &buf[0], C.uintptr_t(capacity)))
	runtime.KeepAlive(ind)
	if n <= 0 {
		return nil
	}
	out := make([]FootprintLevel, n)
	for i := 0; i < n; i++ {
		out[i] = FootprintLevel{float64(buf[i].price), float64(buf[i].bid_vol), float64(buf[i].ask_vol)}
	}
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Footprint) Reset() {
	C.wickra_footprint_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Footprint) Close() {
	if ind.handle != nil {
		C.wickra_footprint_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ForceIndex wraps the ForceIndex indicator over the Wickra C ABI.
type ForceIndex struct {
	handle *C.struct_ForceIndex
}

// NewForceIndex constructs a ForceIndex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewForceIndex(period int) (*ForceIndex, error) {
	ptr := C.wickra_force_index_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ForceIndex{handle: ptr}
	runtime.SetFinalizer(obj, (*ForceIndex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ForceIndex) WarmupPeriod() int {
	r := int(C.wickra_force_index_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ForceIndex) IsReady() bool {
	r := bool(C.wickra_force_index_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ForceIndex) Name() string {
	r := C.GoString(C.wickra_force_index_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ForceIndex) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_force_index_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ForceIndex) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_force_index_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ForceIndex) Reset() {
	C.wickra_force_index_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ForceIndex) Close() {
	if ind.handle != nil {
		C.wickra_force_index_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FractalChaosBands wraps the FractalChaosBands indicator over the Wickra C ABI.
type FractalChaosBands struct {
	handle *C.struct_FractalChaosBands
}

// NewFractalChaosBands constructs a FractalChaosBands. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFractalChaosBands(k int) (*FractalChaosBands, error) {
	ptr := C.wickra_fractal_chaos_bands_new(C.uintptr_t(k))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FractalChaosBands{handle: ptr}
	runtime.SetFinalizer(obj, (*FractalChaosBands).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FractalChaosBands) WarmupPeriod() int {
	r := int(C.wickra_fractal_chaos_bands_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FractalChaosBands) IsReady() bool {
	r := bool(C.wickra_fractal_chaos_bands_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FractalChaosBands) Name() string {
	r := C.GoString(C.wickra_fractal_chaos_bands_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *FractalChaosBands) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (FractalChaosBandsOutput, bool) {
	var out C.struct_WickraFractalChaosBandsOutput
	ok := bool(C.wickra_fractal_chaos_bands_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return FractalChaosBandsOutput{}, false
	}
	return FractalChaosBandsOutput{float64(out.upper), float64(out.lower)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FractalChaosBands) Reset() {
	C.wickra_fractal_chaos_bands_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FractalChaosBands) Close() {
	if ind.handle != nil {
		C.wickra_fractal_chaos_bands_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Frama wraps the Frama indicator over the Wickra C ABI.
type Frama struct {
	handle *C.struct_Frama
}

// NewFrama constructs a Frama. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFrama(period int) (*Frama, error) {
	ptr := C.wickra_frama_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Frama{handle: ptr}
	runtime.SetFinalizer(obj, (*Frama).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Frama) WarmupPeriod() int {
	r := int(C.wickra_frama_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Frama) IsReady() bool {
	r := bool(C.wickra_frama_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Frama) Name() string {
	r := C.GoString(C.wickra_frama_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Frama) Update(value float64) float64 {
	r := float64(C.wickra_frama_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Frama) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_frama_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Frama) Reset() {
	C.wickra_frama_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Frama) Close() {
	if ind.handle != nil {
		C.wickra_frama_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FryPanBottom wraps the FryPanBottom indicator over the Wickra C ABI.
type FryPanBottom struct {
	handle *C.struct_FryPanBottom
}

// NewFryPanBottom constructs a FryPanBottom. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFryPanBottom(period int) (*FryPanBottom, error) {
	ptr := C.wickra_fry_pan_bottom_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FryPanBottom{handle: ptr}
	runtime.SetFinalizer(obj, (*FryPanBottom).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FryPanBottom) WarmupPeriod() int {
	r := int(C.wickra_fry_pan_bottom_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FryPanBottom) IsReady() bool {
	r := bool(C.wickra_fry_pan_bottom_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FryPanBottom) Name() string {
	r := C.GoString(C.wickra_fry_pan_bottom_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *FryPanBottom) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_fry_pan_bottom_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *FryPanBottom) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_fry_pan_bottom_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FryPanBottom) Reset() {
	C.wickra_fry_pan_bottom_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FryPanBottom) Close() {
	if ind.handle != nil {
		C.wickra_fry_pan_bottom_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FundingBasis wraps the FundingBasis indicator over the Wickra C ABI.
type FundingBasis struct {
	handle *C.struct_FundingBasis
}

// NewFundingBasis constructs a FundingBasis. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFundingBasis() (*FundingBasis, error) {
	ptr := C.wickra_funding_basis_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FundingBasis{handle: ptr}
	runtime.SetFinalizer(obj, (*FundingBasis).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FundingBasis) WarmupPeriod() int {
	r := int(C.wickra_funding_basis_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FundingBasis) IsReady() bool {
	r := bool(C.wickra_funding_basis_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FundingBasis) Name() string {
	r := C.GoString(C.wickra_funding_basis_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *FundingBasis) Update(fundingRate float64, markPrice float64, indexPrice float64, futuresPrice float64, openInterest float64, longSize float64, shortSize float64, takerBuyVolume float64, takerSellVolume float64, longLiquidation float64, shortLiquidation float64, timestamp int64) float64 {
	r := float64(C.wickra_funding_basis_update(ind.handle, C.double(fundingRate), C.double(markPrice), C.double(indexPrice), C.double(futuresPrice), C.double(openInterest), C.double(longSize), C.double(shortSize), C.double(takerBuyVolume), C.double(takerSellVolume), C.double(longLiquidation), C.double(shortLiquidation), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FundingBasis) Reset() {
	C.wickra_funding_basis_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FundingBasis) Close() {
	if ind.handle != nil {
		C.wickra_funding_basis_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FundingImpliedApr wraps the FundingImpliedApr indicator over the Wickra C ABI.
type FundingImpliedApr struct {
	handle *C.struct_FundingImpliedApr
}

// NewFundingImpliedApr constructs a FundingImpliedApr. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFundingImpliedApr(intervalsPerYear float64) (*FundingImpliedApr, error) {
	ptr := C.wickra_funding_implied_apr_new(C.double(intervalsPerYear))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FundingImpliedApr{handle: ptr}
	runtime.SetFinalizer(obj, (*FundingImpliedApr).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FundingImpliedApr) WarmupPeriod() int {
	r := int(C.wickra_funding_implied_apr_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FundingImpliedApr) IsReady() bool {
	r := bool(C.wickra_funding_implied_apr_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FundingImpliedApr) Name() string {
	r := C.GoString(C.wickra_funding_implied_apr_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *FundingImpliedApr) Update(fundingRate float64, markPrice float64, indexPrice float64, futuresPrice float64, openInterest float64, longSize float64, shortSize float64, takerBuyVolume float64, takerSellVolume float64, longLiquidation float64, shortLiquidation float64, timestamp int64) float64 {
	r := float64(C.wickra_funding_implied_apr_update(ind.handle, C.double(fundingRate), C.double(markPrice), C.double(indexPrice), C.double(futuresPrice), C.double(openInterest), C.double(longSize), C.double(shortSize), C.double(takerBuyVolume), C.double(takerSellVolume), C.double(longLiquidation), C.double(shortLiquidation), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FundingImpliedApr) Reset() {
	C.wickra_funding_implied_apr_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FundingImpliedApr) Close() {
	if ind.handle != nil {
		C.wickra_funding_implied_apr_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FundingRate wraps the FundingRate indicator over the Wickra C ABI.
type FundingRate struct {
	handle *C.struct_FundingRate
}

// NewFundingRate constructs a FundingRate. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFundingRate() (*FundingRate, error) {
	ptr := C.wickra_funding_rate_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FundingRate{handle: ptr}
	runtime.SetFinalizer(obj, (*FundingRate).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FundingRate) WarmupPeriod() int {
	r := int(C.wickra_funding_rate_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FundingRate) IsReady() bool {
	r := bool(C.wickra_funding_rate_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FundingRate) Name() string {
	r := C.GoString(C.wickra_funding_rate_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *FundingRate) Update(fundingRate float64, markPrice float64, indexPrice float64, futuresPrice float64, openInterest float64, longSize float64, shortSize float64, takerBuyVolume float64, takerSellVolume float64, longLiquidation float64, shortLiquidation float64, timestamp int64) float64 {
	r := float64(C.wickra_funding_rate_update(ind.handle, C.double(fundingRate), C.double(markPrice), C.double(indexPrice), C.double(futuresPrice), C.double(openInterest), C.double(longSize), C.double(shortSize), C.double(takerBuyVolume), C.double(takerSellVolume), C.double(longLiquidation), C.double(shortLiquidation), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FundingRate) Reset() {
	C.wickra_funding_rate_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FundingRate) Close() {
	if ind.handle != nil {
		C.wickra_funding_rate_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FundingRateMean wraps the FundingRateMean indicator over the Wickra C ABI.
type FundingRateMean struct {
	handle *C.struct_FundingRateMean
}

// NewFundingRateMean constructs a FundingRateMean. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFundingRateMean(window int) (*FundingRateMean, error) {
	ptr := C.wickra_funding_rate_mean_new(C.uintptr_t(window))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FundingRateMean{handle: ptr}
	runtime.SetFinalizer(obj, (*FundingRateMean).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FundingRateMean) WarmupPeriod() int {
	r := int(C.wickra_funding_rate_mean_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FundingRateMean) IsReady() bool {
	r := bool(C.wickra_funding_rate_mean_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FundingRateMean) Name() string {
	r := C.GoString(C.wickra_funding_rate_mean_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *FundingRateMean) Update(fundingRate float64, markPrice float64, indexPrice float64, futuresPrice float64, openInterest float64, longSize float64, shortSize float64, takerBuyVolume float64, takerSellVolume float64, longLiquidation float64, shortLiquidation float64, timestamp int64) float64 {
	r := float64(C.wickra_funding_rate_mean_update(ind.handle, C.double(fundingRate), C.double(markPrice), C.double(indexPrice), C.double(futuresPrice), C.double(openInterest), C.double(longSize), C.double(shortSize), C.double(takerBuyVolume), C.double(takerSellVolume), C.double(longLiquidation), C.double(shortLiquidation), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FundingRateMean) Reset() {
	C.wickra_funding_rate_mean_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FundingRateMean) Close() {
	if ind.handle != nil {
		C.wickra_funding_rate_mean_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// FundingRateZScore wraps the FundingRateZScore indicator over the Wickra C ABI.
type FundingRateZScore struct {
	handle *C.struct_FundingRateZScore
}

// NewFundingRateZScore constructs a FundingRateZScore. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewFundingRateZScore(window int) (*FundingRateZScore, error) {
	ptr := C.wickra_funding_rate_z_score_new(C.uintptr_t(window))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &FundingRateZScore{handle: ptr}
	runtime.SetFinalizer(obj, (*FundingRateZScore).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *FundingRateZScore) WarmupPeriod() int {
	r := int(C.wickra_funding_rate_z_score_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *FundingRateZScore) IsReady() bool {
	r := bool(C.wickra_funding_rate_z_score_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *FundingRateZScore) Name() string {
	r := C.GoString(C.wickra_funding_rate_z_score_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *FundingRateZScore) Update(fundingRate float64, markPrice float64, indexPrice float64, futuresPrice float64, openInterest float64, longSize float64, shortSize float64, takerBuyVolume float64, takerSellVolume float64, longLiquidation float64, shortLiquidation float64, timestamp int64) float64 {
	r := float64(C.wickra_funding_rate_z_score_update(ind.handle, C.double(fundingRate), C.double(markPrice), C.double(indexPrice), C.double(futuresPrice), C.double(openInterest), C.double(longSize), C.double(shortSize), C.double(takerBuyVolume), C.double(takerSellVolume), C.double(longLiquidation), C.double(shortLiquidation), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *FundingRateZScore) Reset() {
	C.wickra_funding_rate_z_score_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *FundingRateZScore) Close() {
	if ind.handle != nil {
		C.wickra_funding_rate_z_score_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// GainLossRatio wraps the GainLossRatio indicator over the Wickra C ABI.
type GainLossRatio struct {
	handle *C.struct_GainLossRatio
}

// NewGainLossRatio constructs a GainLossRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewGainLossRatio(period int) (*GainLossRatio, error) {
	ptr := C.wickra_gain_loss_ratio_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &GainLossRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*GainLossRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *GainLossRatio) WarmupPeriod() int {
	r := int(C.wickra_gain_loss_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *GainLossRatio) IsReady() bool {
	r := bool(C.wickra_gain_loss_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *GainLossRatio) Name() string {
	r := C.GoString(C.wickra_gain_loss_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *GainLossRatio) Update(value float64) float64 {
	r := float64(C.wickra_gain_loss_ratio_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *GainLossRatio) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_gain_loss_ratio_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *GainLossRatio) Reset() {
	C.wickra_gain_loss_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *GainLossRatio) Close() {
	if ind.handle != nil {
		C.wickra_gain_loss_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// GainToPainRatio wraps the GainToPainRatio indicator over the Wickra C ABI.
type GainToPainRatio struct {
	handle *C.struct_GainToPainRatio
}

// NewGainToPainRatio constructs a GainToPainRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewGainToPainRatio(period int) (*GainToPainRatio, error) {
	ptr := C.wickra_gain_to_pain_ratio_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &GainToPainRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*GainToPainRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *GainToPainRatio) WarmupPeriod() int {
	r := int(C.wickra_gain_to_pain_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *GainToPainRatio) IsReady() bool {
	r := bool(C.wickra_gain_to_pain_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *GainToPainRatio) Name() string {
	r := C.GoString(C.wickra_gain_to_pain_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *GainToPainRatio) Update(value float64) float64 {
	r := float64(C.wickra_gain_to_pain_ratio_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *GainToPainRatio) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_gain_to_pain_ratio_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *GainToPainRatio) Reset() {
	C.wickra_gain_to_pain_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *GainToPainRatio) Close() {
	if ind.handle != nil {
		C.wickra_gain_to_pain_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// GapSideBySideWhite wraps the GapSideBySideWhite indicator over the Wickra C ABI.
type GapSideBySideWhite struct {
	handle *C.struct_GapSideBySideWhite
}

// NewGapSideBySideWhite constructs a GapSideBySideWhite. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewGapSideBySideWhite() (*GapSideBySideWhite, error) {
	ptr := C.wickra_gap_side_by_side_white_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &GapSideBySideWhite{handle: ptr}
	runtime.SetFinalizer(obj, (*GapSideBySideWhite).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *GapSideBySideWhite) WarmupPeriod() int {
	r := int(C.wickra_gap_side_by_side_white_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *GapSideBySideWhite) IsReady() bool {
	r := bool(C.wickra_gap_side_by_side_white_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *GapSideBySideWhite) Name() string {
	r := C.GoString(C.wickra_gap_side_by_side_white_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *GapSideBySideWhite) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_gap_side_by_side_white_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *GapSideBySideWhite) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_gap_side_by_side_white_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *GapSideBySideWhite) Reset() {
	C.wickra_gap_side_by_side_white_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *GapSideBySideWhite) Close() {
	if ind.handle != nil {
		C.wickra_gap_side_by_side_white_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Garch11 wraps the Garch11 indicator over the Wickra C ABI.
type Garch11 struct {
	handle *C.struct_Garch11
}

// NewGarch11 constructs a Garch11. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewGarch11(omega float64, alpha float64, beta float64) (*Garch11, error) {
	ptr := C.wickra_garch11_new(C.double(omega), C.double(alpha), C.double(beta))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Garch11{handle: ptr}
	runtime.SetFinalizer(obj, (*Garch11).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Garch11) WarmupPeriod() int {
	r := int(C.wickra_garch11_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Garch11) IsReady() bool {
	r := bool(C.wickra_garch11_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Garch11) Name() string {
	r := C.GoString(C.wickra_garch11_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Garch11) Update(value float64) float64 {
	r := float64(C.wickra_garch11_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Garch11) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_garch11_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Garch11) Reset() {
	C.wickra_garch11_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Garch11) Close() {
	if ind.handle != nil {
		C.wickra_garch11_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// GarmanKlassVolatility wraps the GarmanKlassVolatility indicator over the Wickra C ABI.
type GarmanKlassVolatility struct {
	handle *C.struct_GarmanKlassVolatility
}

// NewGarmanKlassVolatility constructs a GarmanKlassVolatility. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewGarmanKlassVolatility(period int, tradingPeriods int) (*GarmanKlassVolatility, error) {
	ptr := C.wickra_garman_klass_volatility_new(C.uintptr_t(period), C.uintptr_t(tradingPeriods))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &GarmanKlassVolatility{handle: ptr}
	runtime.SetFinalizer(obj, (*GarmanKlassVolatility).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *GarmanKlassVolatility) WarmupPeriod() int {
	r := int(C.wickra_garman_klass_volatility_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *GarmanKlassVolatility) IsReady() bool {
	r := bool(C.wickra_garman_klass_volatility_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *GarmanKlassVolatility) Name() string {
	r := C.GoString(C.wickra_garman_klass_volatility_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *GarmanKlassVolatility) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_garman_klass_volatility_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *GarmanKlassVolatility) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_garman_klass_volatility_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *GarmanKlassVolatility) Reset() {
	C.wickra_garman_klass_volatility_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *GarmanKlassVolatility) Close() {
	if ind.handle != nil {
		C.wickra_garman_klass_volatility_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Gartley wraps the Gartley indicator over the Wickra C ABI.
type Gartley struct {
	handle *C.struct_Gartley
}

// NewGartley constructs a Gartley. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewGartley() (*Gartley, error) {
	ptr := C.wickra_gartley_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Gartley{handle: ptr}
	runtime.SetFinalizer(obj, (*Gartley).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Gartley) WarmupPeriod() int {
	r := int(C.wickra_gartley_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Gartley) IsReady() bool {
	r := bool(C.wickra_gartley_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Gartley) Name() string {
	r := C.GoString(C.wickra_gartley_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Gartley) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_gartley_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Gartley) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_gartley_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Gartley) Reset() {
	C.wickra_gartley_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Gartley) Close() {
	if ind.handle != nil {
		C.wickra_gartley_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// GatorOscillator wraps the GatorOscillator indicator over the Wickra C ABI.
type GatorOscillator struct {
	handle *C.struct_GatorOscillator
}

// NewGatorOscillator constructs a GatorOscillator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewGatorOscillator(jawPeriod int, teethPeriod int, lipsPeriod int) (*GatorOscillator, error) {
	ptr := C.wickra_gator_oscillator_new(C.uintptr_t(jawPeriod), C.uintptr_t(teethPeriod), C.uintptr_t(lipsPeriod))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &GatorOscillator{handle: ptr}
	runtime.SetFinalizer(obj, (*GatorOscillator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *GatorOscillator) WarmupPeriod() int {
	r := int(C.wickra_gator_oscillator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *GatorOscillator) IsReady() bool {
	r := bool(C.wickra_gator_oscillator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *GatorOscillator) Name() string {
	r := C.GoString(C.wickra_gator_oscillator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *GatorOscillator) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (GatorOscillatorOutput, bool) {
	var out C.struct_WickraGatorOscillatorOutput
	ok := bool(C.wickra_gator_oscillator_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return GatorOscillatorOutput{}, false
	}
	return GatorOscillatorOutput{float64(out.upper), float64(out.lower)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *GatorOscillator) Reset() {
	C.wickra_gator_oscillator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *GatorOscillator) Close() {
	if ind.handle != nil {
		C.wickra_gator_oscillator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// GeneralizedDema wraps the GeneralizedDema indicator over the Wickra C ABI.
type GeneralizedDema struct {
	handle *C.struct_GeneralizedDema
}

// NewGeneralizedDema constructs a GeneralizedDema. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewGeneralizedDema(period int, v float64) (*GeneralizedDema, error) {
	ptr := C.wickra_generalized_dema_new(C.uintptr_t(period), C.double(v))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &GeneralizedDema{handle: ptr}
	runtime.SetFinalizer(obj, (*GeneralizedDema).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *GeneralizedDema) WarmupPeriod() int {
	r := int(C.wickra_generalized_dema_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *GeneralizedDema) IsReady() bool {
	r := bool(C.wickra_generalized_dema_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *GeneralizedDema) Name() string {
	r := C.GoString(C.wickra_generalized_dema_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *GeneralizedDema) Update(value float64) float64 {
	r := float64(C.wickra_generalized_dema_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *GeneralizedDema) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_generalized_dema_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *GeneralizedDema) Reset() {
	C.wickra_generalized_dema_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *GeneralizedDema) Close() {
	if ind.handle != nil {
		C.wickra_generalized_dema_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// GeometricMa wraps the GeometricMa indicator over the Wickra C ABI.
type GeometricMa struct {
	handle *C.struct_GeometricMa
}

// NewGeometricMa constructs a GeometricMa. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewGeometricMa(period int) (*GeometricMa, error) {
	ptr := C.wickra_geometric_ma_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &GeometricMa{handle: ptr}
	runtime.SetFinalizer(obj, (*GeometricMa).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *GeometricMa) WarmupPeriod() int {
	r := int(C.wickra_geometric_ma_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *GeometricMa) IsReady() bool {
	r := bool(C.wickra_geometric_ma_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *GeometricMa) Name() string {
	r := C.GoString(C.wickra_geometric_ma_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *GeometricMa) Update(value float64) float64 {
	r := float64(C.wickra_geometric_ma_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *GeometricMa) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_geometric_ma_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *GeometricMa) Reset() {
	C.wickra_geometric_ma_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *GeometricMa) Close() {
	if ind.handle != nil {
		C.wickra_geometric_ma_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// GoldenPocket wraps the GoldenPocket indicator over the Wickra C ABI.
type GoldenPocket struct {
	handle *C.struct_GoldenPocket
}

// NewGoldenPocket constructs a GoldenPocket. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewGoldenPocket() (*GoldenPocket, error) {
	ptr := C.wickra_golden_pocket_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &GoldenPocket{handle: ptr}
	runtime.SetFinalizer(obj, (*GoldenPocket).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *GoldenPocket) WarmupPeriod() int {
	r := int(C.wickra_golden_pocket_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *GoldenPocket) IsReady() bool {
	r := bool(C.wickra_golden_pocket_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *GoldenPocket) Name() string {
	r := C.GoString(C.wickra_golden_pocket_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *GoldenPocket) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (GoldenPocketOutput, bool) {
	var out C.struct_WickraGoldenPocketOutput
	ok := bool(C.wickra_golden_pocket_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return GoldenPocketOutput{}, false
	}
	return GoldenPocketOutput{float64(out.low), float64(out.mid), float64(out.high)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *GoldenPocket) Reset() {
	C.wickra_golden_pocket_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *GoldenPocket) Close() {
	if ind.handle != nil {
		C.wickra_golden_pocket_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// GrangerCausality wraps the GrangerCausality indicator over the Wickra C ABI.
type GrangerCausality struct {
	handle *C.struct_GrangerCausality
}

// NewGrangerCausality constructs a GrangerCausality. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewGrangerCausality(period int, lag int) (*GrangerCausality, error) {
	ptr := C.wickra_granger_causality_new(C.uintptr_t(period), C.uintptr_t(lag))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &GrangerCausality{handle: ptr}
	runtime.SetFinalizer(obj, (*GrangerCausality).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *GrangerCausality) WarmupPeriod() int {
	r := int(C.wickra_granger_causality_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *GrangerCausality) IsReady() bool {
	r := bool(C.wickra_granger_causality_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *GrangerCausality) Name() string {
	r := C.GoString(C.wickra_granger_causality_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *GrangerCausality) Update(x float64, y float64) float64 {
	r := float64(C.wickra_granger_causality_update(ind.handle, C.double(x), C.double(y)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *GrangerCausality) Batch(x []float64, y []float64) []float64 {
	n := len(x)
	if len(y) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_granger_causality_batch(ind.handle, (*C.double)(unsafe.Pointer(&x[0])), (*C.double)(unsafe.Pointer(&y[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(x)
	runtime.KeepAlive(y)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *GrangerCausality) Reset() {
	C.wickra_granger_causality_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *GrangerCausality) Close() {
	if ind.handle != nil {
		C.wickra_granger_causality_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// GravestoneDoji wraps the GravestoneDoji indicator over the Wickra C ABI.
type GravestoneDoji struct {
	handle *C.struct_GravestoneDoji
}

// NewGravestoneDoji constructs a GravestoneDoji. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewGravestoneDoji() (*GravestoneDoji, error) {
	ptr := C.wickra_gravestone_doji_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &GravestoneDoji{handle: ptr}
	runtime.SetFinalizer(obj, (*GravestoneDoji).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *GravestoneDoji) WarmupPeriod() int {
	r := int(C.wickra_gravestone_doji_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *GravestoneDoji) IsReady() bool {
	r := bool(C.wickra_gravestone_doji_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *GravestoneDoji) Name() string {
	r := C.GoString(C.wickra_gravestone_doji_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *GravestoneDoji) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_gravestone_doji_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *GravestoneDoji) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_gravestone_doji_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *GravestoneDoji) Reset() {
	C.wickra_gravestone_doji_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *GravestoneDoji) Close() {
	if ind.handle != nil {
		C.wickra_gravestone_doji_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Hammer wraps the Hammer indicator over the Wickra C ABI.
type Hammer struct {
	handle *C.struct_Hammer
}

// NewHammer constructs a Hammer. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHammer() (*Hammer, error) {
	ptr := C.wickra_hammer_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Hammer{handle: ptr}
	runtime.SetFinalizer(obj, (*Hammer).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Hammer) WarmupPeriod() int {
	r := int(C.wickra_hammer_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Hammer) IsReady() bool {
	r := bool(C.wickra_hammer_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Hammer) Name() string {
	r := C.GoString(C.wickra_hammer_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Hammer) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_hammer_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Hammer) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_hammer_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Hammer) Reset() {
	C.wickra_hammer_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Hammer) Close() {
	if ind.handle != nil {
		C.wickra_hammer_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HangingMan wraps the HangingMan indicator over the Wickra C ABI.
type HangingMan struct {
	handle *C.struct_HangingMan
}

// NewHangingMan constructs a HangingMan. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHangingMan() (*HangingMan, error) {
	ptr := C.wickra_hanging_man_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HangingMan{handle: ptr}
	runtime.SetFinalizer(obj, (*HangingMan).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HangingMan) WarmupPeriod() int {
	r := int(C.wickra_hanging_man_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HangingMan) IsReady() bool {
	r := bool(C.wickra_hanging_man_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HangingMan) Name() string {
	r := C.GoString(C.wickra_hanging_man_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *HangingMan) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_hanging_man_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *HangingMan) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_hanging_man_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HangingMan) Reset() {
	C.wickra_hanging_man_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HangingMan) Close() {
	if ind.handle != nil {
		C.wickra_hanging_man_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Harami wraps the Harami indicator over the Wickra C ABI.
type Harami struct {
	handle *C.struct_Harami
}

// NewHarami constructs a Harami. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHarami() (*Harami, error) {
	ptr := C.wickra_harami_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Harami{handle: ptr}
	runtime.SetFinalizer(obj, (*Harami).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Harami) WarmupPeriod() int {
	r := int(C.wickra_harami_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Harami) IsReady() bool {
	r := bool(C.wickra_harami_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Harami) Name() string {
	r := C.GoString(C.wickra_harami_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Harami) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_harami_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Harami) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_harami_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Harami) Reset() {
	C.wickra_harami_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Harami) Close() {
	if ind.handle != nil {
		C.wickra_harami_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HaramiCross wraps the HaramiCross indicator over the Wickra C ABI.
type HaramiCross struct {
	handle *C.struct_HaramiCross
}

// NewHaramiCross constructs a HaramiCross. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHaramiCross() (*HaramiCross, error) {
	ptr := C.wickra_harami_cross_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HaramiCross{handle: ptr}
	runtime.SetFinalizer(obj, (*HaramiCross).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HaramiCross) WarmupPeriod() int {
	r := int(C.wickra_harami_cross_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HaramiCross) IsReady() bool {
	r := bool(C.wickra_harami_cross_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HaramiCross) Name() string {
	r := C.GoString(C.wickra_harami_cross_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *HaramiCross) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_harami_cross_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *HaramiCross) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_harami_cross_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HaramiCross) Reset() {
	C.wickra_harami_cross_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HaramiCross) Close() {
	if ind.handle != nil {
		C.wickra_harami_cross_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HasbrouckInformationShare wraps the HasbrouckInformationShare indicator over the Wickra C ABI.
type HasbrouckInformationShare struct {
	handle *C.struct_HasbrouckInformationShare
}

// NewHasbrouckInformationShare constructs a HasbrouckInformationShare. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHasbrouckInformationShare(period int) (*HasbrouckInformationShare, error) {
	ptr := C.wickra_hasbrouck_information_share_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HasbrouckInformationShare{handle: ptr}
	runtime.SetFinalizer(obj, (*HasbrouckInformationShare).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HasbrouckInformationShare) WarmupPeriod() int {
	r := int(C.wickra_hasbrouck_information_share_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HasbrouckInformationShare) IsReady() bool {
	r := bool(C.wickra_hasbrouck_information_share_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HasbrouckInformationShare) Name() string {
	r := C.GoString(C.wickra_hasbrouck_information_share_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *HasbrouckInformationShare) Update(x float64, y float64) float64 {
	r := float64(C.wickra_hasbrouck_information_share_update(ind.handle, C.double(x), C.double(y)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *HasbrouckInformationShare) Batch(x []float64, y []float64) []float64 {
	n := len(x)
	if len(y) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_hasbrouck_information_share_batch(ind.handle, (*C.double)(unsafe.Pointer(&x[0])), (*C.double)(unsafe.Pointer(&y[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(x)
	runtime.KeepAlive(y)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HasbrouckInformationShare) Reset() {
	C.wickra_hasbrouck_information_share_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HasbrouckInformationShare) Close() {
	if ind.handle != nil {
		C.wickra_hasbrouck_information_share_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HeadAndShoulders wraps the HeadAndShoulders indicator over the Wickra C ABI.
type HeadAndShoulders struct {
	handle *C.struct_HeadAndShoulders
}

// NewHeadAndShoulders constructs a HeadAndShoulders. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHeadAndShoulders() (*HeadAndShoulders, error) {
	ptr := C.wickra_head_and_shoulders_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HeadAndShoulders{handle: ptr}
	runtime.SetFinalizer(obj, (*HeadAndShoulders).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HeadAndShoulders) WarmupPeriod() int {
	r := int(C.wickra_head_and_shoulders_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HeadAndShoulders) IsReady() bool {
	r := bool(C.wickra_head_and_shoulders_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HeadAndShoulders) Name() string {
	r := C.GoString(C.wickra_head_and_shoulders_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *HeadAndShoulders) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_head_and_shoulders_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *HeadAndShoulders) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_head_and_shoulders_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HeadAndShoulders) Reset() {
	C.wickra_head_and_shoulders_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HeadAndShoulders) Close() {
	if ind.handle != nil {
		C.wickra_head_and_shoulders_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HeikinAshi wraps the HeikinAshi indicator over the Wickra C ABI.
type HeikinAshi struct {
	handle *C.struct_HeikinAshi
}

// NewHeikinAshi constructs a HeikinAshi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHeikinAshi() (*HeikinAshi, error) {
	ptr := C.wickra_heikin_ashi_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HeikinAshi{handle: ptr}
	runtime.SetFinalizer(obj, (*HeikinAshi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HeikinAshi) WarmupPeriod() int {
	r := int(C.wickra_heikin_ashi_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HeikinAshi) IsReady() bool {
	r := bool(C.wickra_heikin_ashi_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HeikinAshi) Name() string {
	r := C.GoString(C.wickra_heikin_ashi_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *HeikinAshi) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (HeikinAshiOutput, bool) {
	var out C.struct_WickraHeikinAshiOutput
	ok := bool(C.wickra_heikin_ashi_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return HeikinAshiOutput{}, false
	}
	return HeikinAshiOutput{float64(out.open), float64(out.high), float64(out.low), float64(out.close)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HeikinAshi) Reset() {
	C.wickra_heikin_ashi_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HeikinAshi) Close() {
	if ind.handle != nil {
		C.wickra_heikin_ashi_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HeikinAshiOscillator wraps the HeikinAshiOscillator indicator over the Wickra C ABI.
type HeikinAshiOscillator struct {
	handle *C.struct_HeikinAshiOscillator
}

// NewHeikinAshiOscillator constructs a HeikinAshiOscillator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHeikinAshiOscillator(period int) (*HeikinAshiOscillator, error) {
	ptr := C.wickra_heikin_ashi_oscillator_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HeikinAshiOscillator{handle: ptr}
	runtime.SetFinalizer(obj, (*HeikinAshiOscillator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HeikinAshiOscillator) WarmupPeriod() int {
	r := int(C.wickra_heikin_ashi_oscillator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HeikinAshiOscillator) IsReady() bool {
	r := bool(C.wickra_heikin_ashi_oscillator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HeikinAshiOscillator) Name() string {
	r := C.GoString(C.wickra_heikin_ashi_oscillator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *HeikinAshiOscillator) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_heikin_ashi_oscillator_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *HeikinAshiOscillator) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_heikin_ashi_oscillator_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HeikinAshiOscillator) Reset() {
	C.wickra_heikin_ashi_oscillator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HeikinAshiOscillator) Close() {
	if ind.handle != nil {
		C.wickra_heikin_ashi_oscillator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HiLoActivator wraps the HiLoActivator indicator over the Wickra C ABI.
type HiLoActivator struct {
	handle *C.struct_HiLoActivator
}

// NewHiLoActivator constructs a HiLoActivator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHiLoActivator(period int) (*HiLoActivator, error) {
	ptr := C.wickra_hi_lo_activator_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HiLoActivator{handle: ptr}
	runtime.SetFinalizer(obj, (*HiLoActivator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HiLoActivator) WarmupPeriod() int {
	r := int(C.wickra_hi_lo_activator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HiLoActivator) IsReady() bool {
	r := bool(C.wickra_hi_lo_activator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HiLoActivator) Name() string {
	r := C.GoString(C.wickra_hi_lo_activator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *HiLoActivator) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_hi_lo_activator_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *HiLoActivator) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_hi_lo_activator_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HiLoActivator) Reset() {
	C.wickra_hi_lo_activator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HiLoActivator) Close() {
	if ind.handle != nil {
		C.wickra_hi_lo_activator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HighLowIndex wraps the HighLowIndex indicator over the Wickra C ABI.
type HighLowIndex struct {
	handle *C.struct_HighLowIndex
}

// NewHighLowIndex constructs a HighLowIndex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHighLowIndex(period int) (*HighLowIndex, error) {
	ptr := C.wickra_high_low_index_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HighLowIndex{handle: ptr}
	runtime.SetFinalizer(obj, (*HighLowIndex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HighLowIndex) WarmupPeriod() int {
	r := int(C.wickra_high_low_index_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HighLowIndex) IsReady() bool {
	r := bool(C.wickra_high_low_index_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HighLowIndex) Name() string {
	r := C.GoString(C.wickra_high_low_index_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *HighLowIndex) Update(change []float64, volume []float64, newHigh []bool, newLow []bool, aboveMa []bool, onBuySignal []bool, timestamp int64) float64 {
	if len(volume) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newHigh) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newLow) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(aboveMa) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(onBuySignal) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_high_low_index_update(ind.handle, (*C.double)(unsafe.Pointer(&change[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.bool)(unsafe.Pointer(&newHigh[0])), (*C.bool)(unsafe.Pointer(&newLow[0])), (*C.bool)(unsafe.Pointer(&aboveMa[0])), (*C.bool)(unsafe.Pointer(&onBuySignal[0])), C.uintptr_t(len(change)), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(change)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(newHigh)
	runtime.KeepAlive(newLow)
	runtime.KeepAlive(aboveMa)
	runtime.KeepAlive(onBuySignal)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HighLowIndex) Reset() {
	C.wickra_high_low_index_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HighLowIndex) Close() {
	if ind.handle != nil {
		C.wickra_high_low_index_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HighLowRange wraps the HighLowRange indicator over the Wickra C ABI.
type HighLowRange struct {
	handle *C.struct_HighLowRange
}

// NewHighLowRange constructs a HighLowRange. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHighLowRange() (*HighLowRange, error) {
	ptr := C.wickra_high_low_range_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HighLowRange{handle: ptr}
	runtime.SetFinalizer(obj, (*HighLowRange).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HighLowRange) WarmupPeriod() int {
	r := int(C.wickra_high_low_range_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HighLowRange) IsReady() bool {
	r := bool(C.wickra_high_low_range_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HighLowRange) Name() string {
	r := C.GoString(C.wickra_high_low_range_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *HighLowRange) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_high_low_range_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *HighLowRange) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_high_low_range_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HighLowRange) Reset() {
	C.wickra_high_low_range_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HighLowRange) Close() {
	if ind.handle != nil {
		C.wickra_high_low_range_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HighLowVolumeNodes wraps the HighLowVolumeNodes indicator over the Wickra C ABI.
type HighLowVolumeNodes struct {
	handle *C.struct_HighLowVolumeNodes
}

// NewHighLowVolumeNodes constructs a HighLowVolumeNodes. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHighLowVolumeNodes(period int, bins int) (*HighLowVolumeNodes, error) {
	ptr := C.wickra_high_low_volume_nodes_new(C.uintptr_t(period), C.uintptr_t(bins))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HighLowVolumeNodes{handle: ptr}
	runtime.SetFinalizer(obj, (*HighLowVolumeNodes).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HighLowVolumeNodes) WarmupPeriod() int {
	r := int(C.wickra_high_low_volume_nodes_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HighLowVolumeNodes) IsReady() bool {
	r := bool(C.wickra_high_low_volume_nodes_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HighLowVolumeNodes) Name() string {
	r := C.GoString(C.wickra_high_low_volume_nodes_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *HighLowVolumeNodes) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (HighLowVolumeNodesOutput, bool) {
	var out C.struct_WickraHighLowVolumeNodesOutput
	ok := bool(C.wickra_high_low_volume_nodes_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return HighLowVolumeNodesOutput{}, false
	}
	return HighLowVolumeNodesOutput{float64(out.hvn), float64(out.lvn)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HighLowVolumeNodes) Reset() {
	C.wickra_high_low_volume_nodes_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HighLowVolumeNodes) Close() {
	if ind.handle != nil {
		C.wickra_high_low_volume_nodes_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HighWave wraps the HighWave indicator over the Wickra C ABI.
type HighWave struct {
	handle *C.struct_HighWave
}

// NewHighWave constructs a HighWave. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHighWave() (*HighWave, error) {
	ptr := C.wickra_high_wave_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HighWave{handle: ptr}
	runtime.SetFinalizer(obj, (*HighWave).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HighWave) WarmupPeriod() int {
	r := int(C.wickra_high_wave_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HighWave) IsReady() bool {
	r := bool(C.wickra_high_wave_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HighWave) Name() string {
	r := C.GoString(C.wickra_high_wave_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *HighWave) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_high_wave_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *HighWave) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_high_wave_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HighWave) Reset() {
	C.wickra_high_wave_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HighWave) Close() {
	if ind.handle != nil {
		C.wickra_high_wave_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HighpassFilter wraps the HighpassFilter indicator over the Wickra C ABI.
type HighpassFilter struct {
	handle *C.struct_HighpassFilter
}

// NewHighpassFilter constructs a HighpassFilter. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHighpassFilter(period int) (*HighpassFilter, error) {
	ptr := C.wickra_highpass_filter_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HighpassFilter{handle: ptr}
	runtime.SetFinalizer(obj, (*HighpassFilter).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HighpassFilter) WarmupPeriod() int {
	r := int(C.wickra_highpass_filter_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HighpassFilter) IsReady() bool {
	r := bool(C.wickra_highpass_filter_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HighpassFilter) Name() string {
	r := C.GoString(C.wickra_highpass_filter_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *HighpassFilter) Update(value float64) float64 {
	r := float64(C.wickra_highpass_filter_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *HighpassFilter) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_highpass_filter_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HighpassFilter) Reset() {
	C.wickra_highpass_filter_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HighpassFilter) Close() {
	if ind.handle != nil {
		C.wickra_highpass_filter_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Hikkake wraps the Hikkake indicator over the Wickra C ABI.
type Hikkake struct {
	handle *C.struct_Hikkake
}

// NewHikkake constructs a Hikkake. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHikkake() (*Hikkake, error) {
	ptr := C.wickra_hikkake_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Hikkake{handle: ptr}
	runtime.SetFinalizer(obj, (*Hikkake).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Hikkake) WarmupPeriod() int {
	r := int(C.wickra_hikkake_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Hikkake) IsReady() bool {
	r := bool(C.wickra_hikkake_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Hikkake) Name() string {
	r := C.GoString(C.wickra_hikkake_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Hikkake) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_hikkake_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Hikkake) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_hikkake_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Hikkake) Reset() {
	C.wickra_hikkake_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Hikkake) Close() {
	if ind.handle != nil {
		C.wickra_hikkake_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HikkakeModified wraps the HikkakeModified indicator over the Wickra C ABI.
type HikkakeModified struct {
	handle *C.struct_HikkakeModified
}

// NewHikkakeModified constructs a HikkakeModified. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHikkakeModified() (*HikkakeModified, error) {
	ptr := C.wickra_hikkake_modified_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HikkakeModified{handle: ptr}
	runtime.SetFinalizer(obj, (*HikkakeModified).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HikkakeModified) WarmupPeriod() int {
	r := int(C.wickra_hikkake_modified_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HikkakeModified) IsReady() bool {
	r := bool(C.wickra_hikkake_modified_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HikkakeModified) Name() string {
	r := C.GoString(C.wickra_hikkake_modified_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *HikkakeModified) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_hikkake_modified_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *HikkakeModified) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_hikkake_modified_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HikkakeModified) Reset() {
	C.wickra_hikkake_modified_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HikkakeModified) Close() {
	if ind.handle != nil {
		C.wickra_hikkake_modified_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HilbertDominantCycle wraps the HilbertDominantCycle indicator over the Wickra C ABI.
type HilbertDominantCycle struct {
	handle *C.struct_HilbertDominantCycle
}

// NewHilbertDominantCycle constructs a HilbertDominantCycle. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHilbertDominantCycle() (*HilbertDominantCycle, error) {
	ptr := C.wickra_hilbert_dominant_cycle_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HilbertDominantCycle{handle: ptr}
	runtime.SetFinalizer(obj, (*HilbertDominantCycle).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HilbertDominantCycle) WarmupPeriod() int {
	r := int(C.wickra_hilbert_dominant_cycle_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HilbertDominantCycle) IsReady() bool {
	r := bool(C.wickra_hilbert_dominant_cycle_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HilbertDominantCycle) Name() string {
	r := C.GoString(C.wickra_hilbert_dominant_cycle_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *HilbertDominantCycle) Update(value float64) float64 {
	r := float64(C.wickra_hilbert_dominant_cycle_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *HilbertDominantCycle) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_hilbert_dominant_cycle_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HilbertDominantCycle) Reset() {
	C.wickra_hilbert_dominant_cycle_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HilbertDominantCycle) Close() {
	if ind.handle != nil {
		C.wickra_hilbert_dominant_cycle_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HistoricalVolatility wraps the HistoricalVolatility indicator over the Wickra C ABI.
type HistoricalVolatility struct {
	handle *C.struct_HistoricalVolatility
}

// NewHistoricalVolatility constructs a HistoricalVolatility. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHistoricalVolatility(period int, tradingPeriods int) (*HistoricalVolatility, error) {
	ptr := C.wickra_historical_volatility_new(C.uintptr_t(period), C.uintptr_t(tradingPeriods))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HistoricalVolatility{handle: ptr}
	runtime.SetFinalizer(obj, (*HistoricalVolatility).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HistoricalVolatility) WarmupPeriod() int {
	r := int(C.wickra_historical_volatility_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HistoricalVolatility) IsReady() bool {
	r := bool(C.wickra_historical_volatility_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HistoricalVolatility) Name() string {
	r := C.GoString(C.wickra_historical_volatility_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *HistoricalVolatility) Update(value float64) float64 {
	r := float64(C.wickra_historical_volatility_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *HistoricalVolatility) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_historical_volatility_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HistoricalVolatility) Reset() {
	C.wickra_historical_volatility_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HistoricalVolatility) Close() {
	if ind.handle != nil {
		C.wickra_historical_volatility_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Hma wraps the Hma indicator over the Wickra C ABI.
type Hma struct {
	handle *C.struct_Hma
}

// NewHma constructs a Hma. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHma(period int) (*Hma, error) {
	ptr := C.wickra_hma_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Hma{handle: ptr}
	runtime.SetFinalizer(obj, (*Hma).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Hma) WarmupPeriod() int {
	r := int(C.wickra_hma_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Hma) IsReady() bool {
	r := bool(C.wickra_hma_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Hma) Name() string {
	r := C.GoString(C.wickra_hma_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Hma) Update(value float64) float64 {
	r := float64(C.wickra_hma_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Hma) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_hma_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Hma) Reset() {
	C.wickra_hma_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Hma) Close() {
	if ind.handle != nil {
		C.wickra_hma_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HoltWinters wraps the HoltWinters indicator over the Wickra C ABI.
type HoltWinters struct {
	handle *C.struct_HoltWinters
}

// NewHoltWinters constructs a HoltWinters. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHoltWinters(alpha float64, beta float64) (*HoltWinters, error) {
	ptr := C.wickra_holt_winters_new(C.double(alpha), C.double(beta))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HoltWinters{handle: ptr}
	runtime.SetFinalizer(obj, (*HoltWinters).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HoltWinters) WarmupPeriod() int {
	r := int(C.wickra_holt_winters_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HoltWinters) IsReady() bool {
	r := bool(C.wickra_holt_winters_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HoltWinters) Name() string {
	r := C.GoString(C.wickra_holt_winters_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *HoltWinters) Update(value float64) float64 {
	r := float64(C.wickra_holt_winters_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *HoltWinters) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_holt_winters_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HoltWinters) Reset() {
	C.wickra_holt_winters_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HoltWinters) Close() {
	if ind.handle != nil {
		C.wickra_holt_winters_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HomingPigeon wraps the HomingPigeon indicator over the Wickra C ABI.
type HomingPigeon struct {
	handle *C.struct_HomingPigeon
}

// NewHomingPigeon constructs a HomingPigeon. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHomingPigeon() (*HomingPigeon, error) {
	ptr := C.wickra_homing_pigeon_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HomingPigeon{handle: ptr}
	runtime.SetFinalizer(obj, (*HomingPigeon).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HomingPigeon) WarmupPeriod() int {
	r := int(C.wickra_homing_pigeon_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HomingPigeon) IsReady() bool {
	r := bool(C.wickra_homing_pigeon_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HomingPigeon) Name() string {
	r := C.GoString(C.wickra_homing_pigeon_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *HomingPigeon) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_homing_pigeon_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *HomingPigeon) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_homing_pigeon_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HomingPigeon) Reset() {
	C.wickra_homing_pigeon_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HomingPigeon) Close() {
	if ind.handle != nil {
		C.wickra_homing_pigeon_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HtDcPhase wraps the HtDcPhase indicator over the Wickra C ABI.
type HtDcPhase struct {
	handle *C.struct_HtDcPhase
}

// NewHtDcPhase constructs a HtDcPhase. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHtDcPhase() (*HtDcPhase, error) {
	ptr := C.wickra_ht_dc_phase_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HtDcPhase{handle: ptr}
	runtime.SetFinalizer(obj, (*HtDcPhase).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HtDcPhase) WarmupPeriod() int {
	r := int(C.wickra_ht_dc_phase_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HtDcPhase) IsReady() bool {
	r := bool(C.wickra_ht_dc_phase_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HtDcPhase) Name() string {
	r := C.GoString(C.wickra_ht_dc_phase_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *HtDcPhase) Update(value float64) float64 {
	r := float64(C.wickra_ht_dc_phase_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *HtDcPhase) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_ht_dc_phase_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HtDcPhase) Reset() {
	C.wickra_ht_dc_phase_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HtDcPhase) Close() {
	if ind.handle != nil {
		C.wickra_ht_dc_phase_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HtPhasor wraps the HtPhasor indicator over the Wickra C ABI.
type HtPhasor struct {
	handle *C.struct_HtPhasor
}

// NewHtPhasor constructs a HtPhasor. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHtPhasor() (*HtPhasor, error) {
	ptr := C.wickra_ht_phasor_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HtPhasor{handle: ptr}
	runtime.SetFinalizer(obj, (*HtPhasor).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HtPhasor) WarmupPeriod() int {
	r := int(C.wickra_ht_phasor_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HtPhasor) IsReady() bool {
	r := bool(C.wickra_ht_phasor_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HtPhasor) Name() string {
	r := C.GoString(C.wickra_ht_phasor_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *HtPhasor) Update(value float64) (HtPhasorOutput, bool) {
	var out C.struct_WickraHtPhasorOutput
	ok := bool(C.wickra_ht_phasor_update(ind.handle, C.double(value), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return HtPhasorOutput{}, false
	}
	return HtPhasorOutput{float64(out.inphase), float64(out.quadrature)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HtPhasor) Reset() {
	C.wickra_ht_phasor_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HtPhasor) Close() {
	if ind.handle != nil {
		C.wickra_ht_phasor_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HtTrendMode wraps the HtTrendMode indicator over the Wickra C ABI.
type HtTrendMode struct {
	handle *C.struct_HtTrendMode
}

// NewHtTrendMode constructs a HtTrendMode. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHtTrendMode() (*HtTrendMode, error) {
	ptr := C.wickra_ht_trend_mode_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HtTrendMode{handle: ptr}
	runtime.SetFinalizer(obj, (*HtTrendMode).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HtTrendMode) WarmupPeriod() int {
	r := int(C.wickra_ht_trend_mode_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HtTrendMode) IsReady() bool {
	r := bool(C.wickra_ht_trend_mode_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HtTrendMode) Name() string {
	r := C.GoString(C.wickra_ht_trend_mode_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *HtTrendMode) Update(value float64) float64 {
	r := float64(C.wickra_ht_trend_mode_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *HtTrendMode) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_ht_trend_mode_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HtTrendMode) Reset() {
	C.wickra_ht_trend_mode_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HtTrendMode) Close() {
	if ind.handle != nil {
		C.wickra_ht_trend_mode_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HurstChannel wraps the HurstChannel indicator over the Wickra C ABI.
type HurstChannel struct {
	handle *C.struct_HurstChannel
}

// NewHurstChannel constructs a HurstChannel. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHurstChannel(period int, multiplier float64) (*HurstChannel, error) {
	ptr := C.wickra_hurst_channel_new(C.uintptr_t(period), C.double(multiplier))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HurstChannel{handle: ptr}
	runtime.SetFinalizer(obj, (*HurstChannel).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HurstChannel) WarmupPeriod() int {
	r := int(C.wickra_hurst_channel_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HurstChannel) IsReady() bool {
	r := bool(C.wickra_hurst_channel_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HurstChannel) Name() string {
	r := C.GoString(C.wickra_hurst_channel_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *HurstChannel) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (HurstChannelOutput, bool) {
	var out C.struct_WickraHurstChannelOutput
	ok := bool(C.wickra_hurst_channel_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return HurstChannelOutput{}, false
	}
	return HurstChannelOutput{float64(out.upper), float64(out.middle), float64(out.lower)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HurstChannel) Reset() {
	C.wickra_hurst_channel_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HurstChannel) Close() {
	if ind.handle != nil {
		C.wickra_hurst_channel_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// HurstExponent wraps the HurstExponent indicator over the Wickra C ABI.
type HurstExponent struct {
	handle *C.struct_HurstExponent
}

// NewHurstExponent constructs a HurstExponent. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewHurstExponent(period int, chunks int) (*HurstExponent, error) {
	ptr := C.wickra_hurst_exponent_new(C.uintptr_t(period), C.uintptr_t(chunks))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &HurstExponent{handle: ptr}
	runtime.SetFinalizer(obj, (*HurstExponent).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *HurstExponent) WarmupPeriod() int {
	r := int(C.wickra_hurst_exponent_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *HurstExponent) IsReady() bool {
	r := bool(C.wickra_hurst_exponent_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *HurstExponent) Name() string {
	r := C.GoString(C.wickra_hurst_exponent_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *HurstExponent) Update(value float64) float64 {
	r := float64(C.wickra_hurst_exponent_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *HurstExponent) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_hurst_exponent_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *HurstExponent) Reset() {
	C.wickra_hurst_exponent_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *HurstExponent) Close() {
	if ind.handle != nil {
		C.wickra_hurst_exponent_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Ichimoku wraps the Ichimoku indicator over the Wickra C ABI.
type Ichimoku struct {
	handle *C.struct_Ichimoku
}

// NewIchimoku constructs a Ichimoku. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewIchimoku(tenkanPeriod int, kijunPeriod int, senkouBPeriod int, displacement int) (*Ichimoku, error) {
	ptr := C.wickra_ichimoku_new(C.uintptr_t(tenkanPeriod), C.uintptr_t(kijunPeriod), C.uintptr_t(senkouBPeriod), C.uintptr_t(displacement))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Ichimoku{handle: ptr}
	runtime.SetFinalizer(obj, (*Ichimoku).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Ichimoku) WarmupPeriod() int {
	r := int(C.wickra_ichimoku_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Ichimoku) IsReady() bool {
	r := bool(C.wickra_ichimoku_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Ichimoku) Name() string {
	r := C.GoString(C.wickra_ichimoku_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *Ichimoku) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (IchimokuOutput, bool) {
	var out C.struct_WickraIchimokuOutput
	ok := bool(C.wickra_ichimoku_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return IchimokuOutput{}, false
	}
	return IchimokuOutput{float64(out.tenkan), float64(out.kijun), float64(out.senkou_a), float64(out.senkou_b), float64(out.chikou)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Ichimoku) Reset() {
	C.wickra_ichimoku_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Ichimoku) Close() {
	if ind.handle != nil {
		C.wickra_ichimoku_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// IdenticalThreeCrows wraps the IdenticalThreeCrows indicator over the Wickra C ABI.
type IdenticalThreeCrows struct {
	handle *C.struct_IdenticalThreeCrows
}

// NewIdenticalThreeCrows constructs a IdenticalThreeCrows. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewIdenticalThreeCrows() (*IdenticalThreeCrows, error) {
	ptr := C.wickra_identical_three_crows_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &IdenticalThreeCrows{handle: ptr}
	runtime.SetFinalizer(obj, (*IdenticalThreeCrows).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *IdenticalThreeCrows) WarmupPeriod() int {
	r := int(C.wickra_identical_three_crows_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *IdenticalThreeCrows) IsReady() bool {
	r := bool(C.wickra_identical_three_crows_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *IdenticalThreeCrows) Name() string {
	r := C.GoString(C.wickra_identical_three_crows_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *IdenticalThreeCrows) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_identical_three_crows_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *IdenticalThreeCrows) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_identical_three_crows_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *IdenticalThreeCrows) Reset() {
	C.wickra_identical_three_crows_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *IdenticalThreeCrows) Close() {
	if ind.handle != nil {
		C.wickra_identical_three_crows_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ImbalanceBars wraps the ImbalanceBars indicator over the Wickra C ABI.
type ImbalanceBars struct {
	handle *C.struct_ImbalanceBars
}

// NewImbalanceBars constructs a ImbalanceBars. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewImbalanceBars(threshold float64) (*ImbalanceBars, error) {
	ptr := C.wickra_imbalance_bars_new(C.double(threshold))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ImbalanceBars{handle: ptr}
	runtime.SetFinalizer(obj, (*ImbalanceBars).Close)
	return obj, nil
}

// Name returns the indicator's canonical name.
func (ind *ImbalanceBars) Name() string {
	r := C.GoString(C.wickra_imbalance_bars_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one candle and returns any bars completed by it
// (a single candle may complete several).
func (ind *ImbalanceBars) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) []ImbalanceBar {
	const capacity = 64
	var buf [capacity]C.struct_WickraImbalanceBar
	n := int(C.wickra_imbalance_bars_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &buf[0], C.uintptr_t(capacity)))
	runtime.KeepAlive(ind)
	if n <= 0 {
		return nil
	}
	out := make([]ImbalanceBar, n)
	for i := 0; i < n; i++ {
		out[i] = ImbalanceBar{float64(buf[i].open), float64(buf[i].high), float64(buf[i].low), float64(buf[i].close), float64(buf[i].imbalance), int8(buf[i].direction)}
	}
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ImbalanceBars) Reset() {
	C.wickra_imbalance_bars_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ImbalanceBars) Close() {
	if ind.handle != nil {
		C.wickra_imbalance_bars_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// InNeck wraps the InNeck indicator over the Wickra C ABI.
type InNeck struct {
	handle *C.struct_InNeck
}

// NewInNeck constructs a InNeck. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewInNeck() (*InNeck, error) {
	ptr := C.wickra_in_neck_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &InNeck{handle: ptr}
	runtime.SetFinalizer(obj, (*InNeck).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *InNeck) WarmupPeriod() int {
	r := int(C.wickra_in_neck_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *InNeck) IsReady() bool {
	r := bool(C.wickra_in_neck_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *InNeck) Name() string {
	r := C.GoString(C.wickra_in_neck_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *InNeck) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_in_neck_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *InNeck) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_in_neck_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *InNeck) Reset() {
	C.wickra_in_neck_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *InNeck) Close() {
	if ind.handle != nil {
		C.wickra_in_neck_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Inertia wraps the Inertia indicator over the Wickra C ABI.
type Inertia struct {
	handle *C.struct_Inertia
}

// NewInertia constructs a Inertia. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewInertia(rviPeriod int, linregPeriod int) (*Inertia, error) {
	ptr := C.wickra_inertia_new(C.uintptr_t(rviPeriod), C.uintptr_t(linregPeriod))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Inertia{handle: ptr}
	runtime.SetFinalizer(obj, (*Inertia).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Inertia) WarmupPeriod() int {
	r := int(C.wickra_inertia_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Inertia) IsReady() bool {
	r := bool(C.wickra_inertia_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Inertia) Name() string {
	r := C.GoString(C.wickra_inertia_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Inertia) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_inertia_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Inertia) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_inertia_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Inertia) Reset() {
	C.wickra_inertia_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Inertia) Close() {
	if ind.handle != nil {
		C.wickra_inertia_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// InformationRatio wraps the InformationRatio indicator over the Wickra C ABI.
type InformationRatio struct {
	handle *C.struct_InformationRatio
}

// NewInformationRatio constructs a InformationRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewInformationRatio(period int) (*InformationRatio, error) {
	ptr := C.wickra_information_ratio_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &InformationRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*InformationRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *InformationRatio) WarmupPeriod() int {
	r := int(C.wickra_information_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *InformationRatio) IsReady() bool {
	r := bool(C.wickra_information_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *InformationRatio) Name() string {
	r := C.GoString(C.wickra_information_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *InformationRatio) Update(x float64, y float64) float64 {
	r := float64(C.wickra_information_ratio_update(ind.handle, C.double(x), C.double(y)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *InformationRatio) Batch(x []float64, y []float64) []float64 {
	n := len(x)
	if len(y) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_information_ratio_batch(ind.handle, (*C.double)(unsafe.Pointer(&x[0])), (*C.double)(unsafe.Pointer(&y[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(x)
	runtime.KeepAlive(y)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *InformationRatio) Reset() {
	C.wickra_information_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *InformationRatio) Close() {
	if ind.handle != nil {
		C.wickra_information_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// InitialBalance wraps the InitialBalance indicator over the Wickra C ABI.
type InitialBalance struct {
	handle *C.struct_InitialBalance
}

// NewInitialBalance constructs a InitialBalance. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewInitialBalance(period int) (*InitialBalance, error) {
	ptr := C.wickra_initial_balance_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &InitialBalance{handle: ptr}
	runtime.SetFinalizer(obj, (*InitialBalance).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *InitialBalance) WarmupPeriod() int {
	r := int(C.wickra_initial_balance_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *InitialBalance) IsReady() bool {
	r := bool(C.wickra_initial_balance_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *InitialBalance) Name() string {
	r := C.GoString(C.wickra_initial_balance_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *InitialBalance) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (InitialBalanceOutput, bool) {
	var out C.struct_WickraInitialBalanceOutput
	ok := bool(C.wickra_initial_balance_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return InitialBalanceOutput{}, false
	}
	return InitialBalanceOutput{float64(out.high), float64(out.low)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *InitialBalance) Reset() {
	C.wickra_initial_balance_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *InitialBalance) Close() {
	if ind.handle != nil {
		C.wickra_initial_balance_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// InstantaneousTrendline wraps the InstantaneousTrendline indicator over the Wickra C ABI.
type InstantaneousTrendline struct {
	handle *C.struct_InstantaneousTrendline
}

// NewInstantaneousTrendline constructs a InstantaneousTrendline. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewInstantaneousTrendline(period int) (*InstantaneousTrendline, error) {
	ptr := C.wickra_instantaneous_trendline_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &InstantaneousTrendline{handle: ptr}
	runtime.SetFinalizer(obj, (*InstantaneousTrendline).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *InstantaneousTrendline) WarmupPeriod() int {
	r := int(C.wickra_instantaneous_trendline_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *InstantaneousTrendline) IsReady() bool {
	r := bool(C.wickra_instantaneous_trendline_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *InstantaneousTrendline) Name() string {
	r := C.GoString(C.wickra_instantaneous_trendline_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *InstantaneousTrendline) Update(value float64) float64 {
	r := float64(C.wickra_instantaneous_trendline_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *InstantaneousTrendline) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_instantaneous_trendline_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *InstantaneousTrendline) Reset() {
	C.wickra_instantaneous_trendline_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *InstantaneousTrendline) Close() {
	if ind.handle != nil {
		C.wickra_instantaneous_trendline_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// IntradayIntensity wraps the IntradayIntensity indicator over the Wickra C ABI.
type IntradayIntensity struct {
	handle *C.struct_IntradayIntensity
}

// NewIntradayIntensity constructs a IntradayIntensity. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewIntradayIntensity() (*IntradayIntensity, error) {
	ptr := C.wickra_intraday_intensity_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &IntradayIntensity{handle: ptr}
	runtime.SetFinalizer(obj, (*IntradayIntensity).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *IntradayIntensity) WarmupPeriod() int {
	r := int(C.wickra_intraday_intensity_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *IntradayIntensity) IsReady() bool {
	r := bool(C.wickra_intraday_intensity_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *IntradayIntensity) Name() string {
	r := C.GoString(C.wickra_intraday_intensity_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *IntradayIntensity) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_intraday_intensity_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *IntradayIntensity) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_intraday_intensity_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *IntradayIntensity) Reset() {
	C.wickra_intraday_intensity_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *IntradayIntensity) Close() {
	if ind.handle != nil {
		C.wickra_intraday_intensity_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// IntradayMomentumIndex wraps the IntradayMomentumIndex indicator over the Wickra C ABI.
type IntradayMomentumIndex struct {
	handle *C.struct_IntradayMomentumIndex
}

// NewIntradayMomentumIndex constructs a IntradayMomentumIndex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewIntradayMomentumIndex(period int) (*IntradayMomentumIndex, error) {
	ptr := C.wickra_intraday_momentum_index_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &IntradayMomentumIndex{handle: ptr}
	runtime.SetFinalizer(obj, (*IntradayMomentumIndex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *IntradayMomentumIndex) WarmupPeriod() int {
	r := int(C.wickra_intraday_momentum_index_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *IntradayMomentumIndex) IsReady() bool {
	r := bool(C.wickra_intraday_momentum_index_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *IntradayMomentumIndex) Name() string {
	r := C.GoString(C.wickra_intraday_momentum_index_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *IntradayMomentumIndex) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_intraday_momentum_index_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *IntradayMomentumIndex) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_intraday_momentum_index_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *IntradayMomentumIndex) Reset() {
	C.wickra_intraday_momentum_index_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *IntradayMomentumIndex) Close() {
	if ind.handle != nil {
		C.wickra_intraday_momentum_index_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// IntradayVolatilityProfile wraps the IntradayVolatilityProfile indicator over the Wickra C ABI.
type IntradayVolatilityProfile struct {
	handle    *C.struct_IntradayVolatilityProfile
	valuesCap int
}

// NewIntradayVolatilityProfile constructs a IntradayVolatilityProfile. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewIntradayVolatilityProfile(buckets int, utcOffsetMinutes int32) (*IntradayVolatilityProfile, error) {
	ptr := C.wickra_intraday_volatility_profile_new(C.uintptr_t(buckets), C.int32_t(utcOffsetMinutes))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &IntradayVolatilityProfile{handle: ptr}
	obj.valuesCap = buckets
	runtime.SetFinalizer(obj, (*IntradayVolatilityProfile).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *IntradayVolatilityProfile) WarmupPeriod() int {
	r := int(C.wickra_intraday_volatility_profile_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *IntradayVolatilityProfile) IsReady() bool {
	r := bool(C.wickra_intraday_volatility_profile_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *IntradayVolatilityProfile) Name() string {
	r := C.GoString(C.wickra_intraday_volatility_profile_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the profile values
// (ok is false during warmup).
func (ind *IntradayVolatilityProfile) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) ([]float64, bool) {
	values := make([]float64, ind.valuesCap)
	n := int(C.wickra_intraday_volatility_profile_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), (*C.double)(unsafe.Pointer(&values[0])), C.uintptr_t(len(values))))
	runtime.KeepAlive(ind)
	if n < 0 {
		return nil, false
	}
	return values[:n], true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *IntradayVolatilityProfile) Reset() {
	C.wickra_intraday_volatility_profile_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *IntradayVolatilityProfile) Close() {
	if ind.handle != nil {
		C.wickra_intraday_volatility_profile_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// InverseFisherTransform wraps the InverseFisherTransform indicator over the Wickra C ABI.
type InverseFisherTransform struct {
	handle *C.struct_InverseFisherTransform
}

// NewInverseFisherTransform constructs a InverseFisherTransform. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewInverseFisherTransform(scale float64) (*InverseFisherTransform, error) {
	ptr := C.wickra_inverse_fisher_transform_new(C.double(scale))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &InverseFisherTransform{handle: ptr}
	runtime.SetFinalizer(obj, (*InverseFisherTransform).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *InverseFisherTransform) WarmupPeriod() int {
	r := int(C.wickra_inverse_fisher_transform_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *InverseFisherTransform) IsReady() bool {
	r := bool(C.wickra_inverse_fisher_transform_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *InverseFisherTransform) Name() string {
	r := C.GoString(C.wickra_inverse_fisher_transform_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *InverseFisherTransform) Update(value float64) float64 {
	r := float64(C.wickra_inverse_fisher_transform_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *InverseFisherTransform) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_inverse_fisher_transform_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *InverseFisherTransform) Reset() {
	C.wickra_inverse_fisher_transform_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *InverseFisherTransform) Close() {
	if ind.handle != nil {
		C.wickra_inverse_fisher_transform_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// InvertedHammer wraps the InvertedHammer indicator over the Wickra C ABI.
type InvertedHammer struct {
	handle *C.struct_InvertedHammer
}

// NewInvertedHammer constructs a InvertedHammer. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewInvertedHammer() (*InvertedHammer, error) {
	ptr := C.wickra_inverted_hammer_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &InvertedHammer{handle: ptr}
	runtime.SetFinalizer(obj, (*InvertedHammer).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *InvertedHammer) WarmupPeriod() int {
	r := int(C.wickra_inverted_hammer_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *InvertedHammer) IsReady() bool {
	r := bool(C.wickra_inverted_hammer_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *InvertedHammer) Name() string {
	r := C.GoString(C.wickra_inverted_hammer_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *InvertedHammer) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_inverted_hammer_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *InvertedHammer) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_inverted_hammer_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *InvertedHammer) Reset() {
	C.wickra_inverted_hammer_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *InvertedHammer) Close() {
	if ind.handle != nil {
		C.wickra_inverted_hammer_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// JarqueBera wraps the JarqueBera indicator over the Wickra C ABI.
type JarqueBera struct {
	handle *C.struct_JarqueBera
}

// NewJarqueBera constructs a JarqueBera. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewJarqueBera(period int) (*JarqueBera, error) {
	ptr := C.wickra_jarque_bera_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &JarqueBera{handle: ptr}
	runtime.SetFinalizer(obj, (*JarqueBera).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *JarqueBera) WarmupPeriod() int {
	r := int(C.wickra_jarque_bera_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *JarqueBera) IsReady() bool {
	r := bool(C.wickra_jarque_bera_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *JarqueBera) Name() string {
	r := C.GoString(C.wickra_jarque_bera_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *JarqueBera) Update(value float64) float64 {
	r := float64(C.wickra_jarque_bera_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *JarqueBera) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_jarque_bera_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *JarqueBera) Reset() {
	C.wickra_jarque_bera_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *JarqueBera) Close() {
	if ind.handle != nil {
		C.wickra_jarque_bera_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Jma wraps the Jma indicator over the Wickra C ABI.
type Jma struct {
	handle *C.struct_Jma
}

// NewJma constructs a Jma. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewJma(period int, phase float64, power uint32) (*Jma, error) {
	ptr := C.wickra_jma_new(C.uintptr_t(period), C.double(phase), C.uint32_t(power))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Jma{handle: ptr}
	runtime.SetFinalizer(obj, (*Jma).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Jma) WarmupPeriod() int {
	r := int(C.wickra_jma_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Jma) IsReady() bool {
	r := bool(C.wickra_jma_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Jma) Name() string {
	r := C.GoString(C.wickra_jma_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Jma) Update(value float64) float64 {
	r := float64(C.wickra_jma_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Jma) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_jma_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Jma) Reset() {
	C.wickra_jma_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Jma) Close() {
	if ind.handle != nil {
		C.wickra_jma_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// JumpIndicator wraps the JumpIndicator indicator over the Wickra C ABI.
type JumpIndicator struct {
	handle *C.struct_JumpIndicator
}

// NewJumpIndicator constructs a JumpIndicator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewJumpIndicator(period int, threshold float64) (*JumpIndicator, error) {
	ptr := C.wickra_jump_indicator_new(C.uintptr_t(period), C.double(threshold))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &JumpIndicator{handle: ptr}
	runtime.SetFinalizer(obj, (*JumpIndicator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *JumpIndicator) WarmupPeriod() int {
	r := int(C.wickra_jump_indicator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *JumpIndicator) IsReady() bool {
	r := bool(C.wickra_jump_indicator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *JumpIndicator) Name() string {
	r := C.GoString(C.wickra_jump_indicator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *JumpIndicator) Update(value float64) float64 {
	r := float64(C.wickra_jump_indicator_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *JumpIndicator) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_jump_indicator_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *JumpIndicator) Reset() {
	C.wickra_jump_indicator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *JumpIndicator) Close() {
	if ind.handle != nil {
		C.wickra_jump_indicator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// KRatio wraps the KRatio indicator over the Wickra C ABI.
type KRatio struct {
	handle *C.struct_KRatio
}

// NewKRatio constructs a KRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewKRatio(period int) (*KRatio, error) {
	ptr := C.wickra_k_ratio_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &KRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*KRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *KRatio) WarmupPeriod() int {
	r := int(C.wickra_k_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *KRatio) IsReady() bool {
	r := bool(C.wickra_k_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *KRatio) Name() string {
	r := C.GoString(C.wickra_k_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *KRatio) Update(value float64) float64 {
	r := float64(C.wickra_k_ratio_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *KRatio) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_k_ratio_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *KRatio) Reset() {
	C.wickra_k_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *KRatio) Close() {
	if ind.handle != nil {
		C.wickra_k_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// KagiBars wraps the KagiBars indicator over the Wickra C ABI.
type KagiBars struct {
	handle *C.struct_KagiBars
}

// NewKagiBars constructs a KagiBars. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewKagiBars(reversal float64) (*KagiBars, error) {
	ptr := C.wickra_kagi_bars_new(C.double(reversal))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &KagiBars{handle: ptr}
	runtime.SetFinalizer(obj, (*KagiBars).Close)
	return obj, nil
}

// Name returns the indicator's canonical name.
func (ind *KagiBars) Name() string {
	r := C.GoString(C.wickra_kagi_bars_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one candle and returns any bars completed by it
// (a single candle may complete several).
func (ind *KagiBars) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) []KagiBar {
	const capacity = 64
	var buf [capacity]C.struct_WickraKagiBar
	n := int(C.wickra_kagi_bars_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &buf[0], C.uintptr_t(capacity)))
	runtime.KeepAlive(ind)
	if n <= 0 {
		return nil
	}
	out := make([]KagiBar, n)
	for i := 0; i < n; i++ {
		out[i] = KagiBar{float64(buf[i].start), float64(buf[i].end), int8(buf[i].direction)}
	}
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *KagiBars) Reset() {
	C.wickra_kagi_bars_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *KagiBars) Close() {
	if ind.handle != nil {
		C.wickra_kagi_bars_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// KalmanHedgeRatio wraps the KalmanHedgeRatio indicator over the Wickra C ABI.
type KalmanHedgeRatio struct {
	handle *C.struct_KalmanHedgeRatio
}

// NewKalmanHedgeRatio constructs a KalmanHedgeRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewKalmanHedgeRatio(delta float64, observationVar float64) (*KalmanHedgeRatio, error) {
	ptr := C.wickra_kalman_hedge_ratio_new(C.double(delta), C.double(observationVar))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &KalmanHedgeRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*KalmanHedgeRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *KalmanHedgeRatio) WarmupPeriod() int {
	r := int(C.wickra_kalman_hedge_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *KalmanHedgeRatio) IsReady() bool {
	r := bool(C.wickra_kalman_hedge_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *KalmanHedgeRatio) Name() string {
	r := C.GoString(C.wickra_kalman_hedge_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *KalmanHedgeRatio) Update(x float64, y float64) (KalmanHedgeRatioOutput, bool) {
	var out C.struct_WickraKalmanHedgeRatioOutput
	ok := bool(C.wickra_kalman_hedge_ratio_update(ind.handle, C.double(x), C.double(y), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return KalmanHedgeRatioOutput{}, false
	}
	return KalmanHedgeRatioOutput{float64(out.hedge_ratio), float64(out.intercept), float64(out.spread)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *KalmanHedgeRatio) Reset() {
	C.wickra_kalman_hedge_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *KalmanHedgeRatio) Close() {
	if ind.handle != nil {
		C.wickra_kalman_hedge_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Kama wraps the Kama indicator over the Wickra C ABI.
type Kama struct {
	handle *C.struct_Kama
}

// NewKama constructs a Kama. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewKama(erPeriod int, fast int, slow int) (*Kama, error) {
	ptr := C.wickra_kama_new(C.uintptr_t(erPeriod), C.uintptr_t(fast), C.uintptr_t(slow))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Kama{handle: ptr}
	runtime.SetFinalizer(obj, (*Kama).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Kama) WarmupPeriod() int {
	r := int(C.wickra_kama_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Kama) IsReady() bool {
	r := bool(C.wickra_kama_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Kama) Name() string {
	r := C.GoString(C.wickra_kama_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Kama) Update(value float64) float64 {
	r := float64(C.wickra_kama_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Kama) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_kama_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Kama) Reset() {
	C.wickra_kama_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Kama) Close() {
	if ind.handle != nil {
		C.wickra_kama_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// KaseDevStop wraps the KaseDevStop indicator over the Wickra C ABI.
type KaseDevStop struct {
	handle *C.struct_KaseDevStop
}

// NewKaseDevStop constructs a KaseDevStop. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewKaseDevStop(period int, dev float64) (*KaseDevStop, error) {
	ptr := C.wickra_kase_dev_stop_new(C.uintptr_t(period), C.double(dev))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &KaseDevStop{handle: ptr}
	runtime.SetFinalizer(obj, (*KaseDevStop).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *KaseDevStop) WarmupPeriod() int {
	r := int(C.wickra_kase_dev_stop_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *KaseDevStop) IsReady() bool {
	r := bool(C.wickra_kase_dev_stop_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *KaseDevStop) Name() string {
	r := C.GoString(C.wickra_kase_dev_stop_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *KaseDevStop) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (KaseDevStopOutput, bool) {
	var out C.struct_WickraKaseDevStopOutput
	ok := bool(C.wickra_kase_dev_stop_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return KaseDevStopOutput{}, false
	}
	return KaseDevStopOutput{float64(out.value), float64(out.direction)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *KaseDevStop) Reset() {
	C.wickra_kase_dev_stop_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *KaseDevStop) Close() {
	if ind.handle != nil {
		C.wickra_kase_dev_stop_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// KasePermissionStochastic wraps the KasePermissionStochastic indicator over the Wickra C ABI.
type KasePermissionStochastic struct {
	handle *C.struct_KasePermissionStochastic
}

// NewKasePermissionStochastic constructs a KasePermissionStochastic. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewKasePermissionStochastic(length int, smooth int) (*KasePermissionStochastic, error) {
	ptr := C.wickra_kase_permission_stochastic_new(C.uintptr_t(length), C.uintptr_t(smooth))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &KasePermissionStochastic{handle: ptr}
	runtime.SetFinalizer(obj, (*KasePermissionStochastic).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *KasePermissionStochastic) WarmupPeriod() int {
	r := int(C.wickra_kase_permission_stochastic_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *KasePermissionStochastic) IsReady() bool {
	r := bool(C.wickra_kase_permission_stochastic_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *KasePermissionStochastic) Name() string {
	r := C.GoString(C.wickra_kase_permission_stochastic_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *KasePermissionStochastic) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (KasePermissionStochasticOutput, bool) {
	var out C.struct_WickraKasePermissionStochasticOutput
	ok := bool(C.wickra_kase_permission_stochastic_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return KasePermissionStochasticOutput{}, false
	}
	return KasePermissionStochasticOutput{float64(out.fast), float64(out.slow)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *KasePermissionStochastic) Reset() {
	C.wickra_kase_permission_stochastic_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *KasePermissionStochastic) Close() {
	if ind.handle != nil {
		C.wickra_kase_permission_stochastic_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// KellyCriterion wraps the KellyCriterion indicator over the Wickra C ABI.
type KellyCriterion struct {
	handle *C.struct_KellyCriterion
}

// NewKellyCriterion constructs a KellyCriterion. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewKellyCriterion(period int) (*KellyCriterion, error) {
	ptr := C.wickra_kelly_criterion_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &KellyCriterion{handle: ptr}
	runtime.SetFinalizer(obj, (*KellyCriterion).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *KellyCriterion) WarmupPeriod() int {
	r := int(C.wickra_kelly_criterion_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *KellyCriterion) IsReady() bool {
	r := bool(C.wickra_kelly_criterion_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *KellyCriterion) Name() string {
	r := C.GoString(C.wickra_kelly_criterion_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *KellyCriterion) Update(value float64) float64 {
	r := float64(C.wickra_kelly_criterion_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *KellyCriterion) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_kelly_criterion_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *KellyCriterion) Reset() {
	C.wickra_kelly_criterion_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *KellyCriterion) Close() {
	if ind.handle != nil {
		C.wickra_kelly_criterion_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Keltner wraps the Keltner indicator over the Wickra C ABI.
type Keltner struct {
	handle *C.struct_Keltner
}

// NewKeltner constructs a Keltner. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewKeltner(emaPeriod int, atrPeriod int, multiplier float64) (*Keltner, error) {
	ptr := C.wickra_keltner_new(C.uintptr_t(emaPeriod), C.uintptr_t(atrPeriod), C.double(multiplier))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Keltner{handle: ptr}
	runtime.SetFinalizer(obj, (*Keltner).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Keltner) WarmupPeriod() int {
	r := int(C.wickra_keltner_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Keltner) IsReady() bool {
	r := bool(C.wickra_keltner_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Keltner) Name() string {
	r := C.GoString(C.wickra_keltner_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *Keltner) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (KeltnerOutput, bool) {
	var out C.struct_WickraKeltnerOutput
	ok := bool(C.wickra_keltner_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return KeltnerOutput{}, false
	}
	return KeltnerOutput{float64(out.upper), float64(out.middle), float64(out.lower)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Keltner) Reset() {
	C.wickra_keltner_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Keltner) Close() {
	if ind.handle != nil {
		C.wickra_keltner_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// KendallTau wraps the KendallTau indicator over the Wickra C ABI.
type KendallTau struct {
	handle *C.struct_KendallTau
}

// NewKendallTau constructs a KendallTau. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewKendallTau(period int) (*KendallTau, error) {
	ptr := C.wickra_kendall_tau_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &KendallTau{handle: ptr}
	runtime.SetFinalizer(obj, (*KendallTau).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *KendallTau) WarmupPeriod() int {
	r := int(C.wickra_kendall_tau_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *KendallTau) IsReady() bool {
	r := bool(C.wickra_kendall_tau_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *KendallTau) Name() string {
	r := C.GoString(C.wickra_kendall_tau_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *KendallTau) Update(x float64, y float64) float64 {
	r := float64(C.wickra_kendall_tau_update(ind.handle, C.double(x), C.double(y)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *KendallTau) Batch(x []float64, y []float64) []float64 {
	n := len(x)
	if len(y) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_kendall_tau_batch(ind.handle, (*C.double)(unsafe.Pointer(&x[0])), (*C.double)(unsafe.Pointer(&y[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(x)
	runtime.KeepAlive(y)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *KendallTau) Reset() {
	C.wickra_kendall_tau_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *KendallTau) Close() {
	if ind.handle != nil {
		C.wickra_kendall_tau_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Kicking wraps the Kicking indicator over the Wickra C ABI.
type Kicking struct {
	handle *C.struct_Kicking
}

// NewKicking constructs a Kicking. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewKicking() (*Kicking, error) {
	ptr := C.wickra_kicking_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Kicking{handle: ptr}
	runtime.SetFinalizer(obj, (*Kicking).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Kicking) WarmupPeriod() int {
	r := int(C.wickra_kicking_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Kicking) IsReady() bool {
	r := bool(C.wickra_kicking_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Kicking) Name() string {
	r := C.GoString(C.wickra_kicking_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Kicking) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_kicking_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Kicking) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_kicking_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Kicking) Reset() {
	C.wickra_kicking_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Kicking) Close() {
	if ind.handle != nil {
		C.wickra_kicking_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// KickingByLength wraps the KickingByLength indicator over the Wickra C ABI.
type KickingByLength struct {
	handle *C.struct_KickingByLength
}

// NewKickingByLength constructs a KickingByLength. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewKickingByLength() (*KickingByLength, error) {
	ptr := C.wickra_kicking_by_length_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &KickingByLength{handle: ptr}
	runtime.SetFinalizer(obj, (*KickingByLength).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *KickingByLength) WarmupPeriod() int {
	r := int(C.wickra_kicking_by_length_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *KickingByLength) IsReady() bool {
	r := bool(C.wickra_kicking_by_length_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *KickingByLength) Name() string {
	r := C.GoString(C.wickra_kicking_by_length_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *KickingByLength) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_kicking_by_length_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *KickingByLength) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_kicking_by_length_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *KickingByLength) Reset() {
	C.wickra_kicking_by_length_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *KickingByLength) Close() {
	if ind.handle != nil {
		C.wickra_kicking_by_length_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Kst wraps the Kst indicator over the Wickra C ABI.
type Kst struct {
	handle *C.struct_Kst
}

// NewKst constructs a Kst. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewKst(roc1 int, roc2 int, roc3 int, roc4 int, sma1 int, sma2 int, sma3 int, sma4 int, signal int) (*Kst, error) {
	ptr := C.wickra_kst_new(C.uintptr_t(roc1), C.uintptr_t(roc2), C.uintptr_t(roc3), C.uintptr_t(roc4), C.uintptr_t(sma1), C.uintptr_t(sma2), C.uintptr_t(sma3), C.uintptr_t(sma4), C.uintptr_t(signal))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Kst{handle: ptr}
	runtime.SetFinalizer(obj, (*Kst).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Kst) WarmupPeriod() int {
	r := int(C.wickra_kst_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Kst) IsReady() bool {
	r := bool(C.wickra_kst_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Kst) Name() string {
	r := C.GoString(C.wickra_kst_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *Kst) Update(value float64) (KstOutput, bool) {
	var out C.struct_WickraKstOutput
	ok := bool(C.wickra_kst_update(ind.handle, C.double(value), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return KstOutput{}, false
	}
	return KstOutput{float64(out.kst), float64(out.signal)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Kst) Reset() {
	C.wickra_kst_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Kst) Close() {
	if ind.handle != nil {
		C.wickra_kst_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Kurtosis wraps the Kurtosis indicator over the Wickra C ABI.
type Kurtosis struct {
	handle *C.struct_Kurtosis
}

// NewKurtosis constructs a Kurtosis. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewKurtosis(period int) (*Kurtosis, error) {
	ptr := C.wickra_kurtosis_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Kurtosis{handle: ptr}
	runtime.SetFinalizer(obj, (*Kurtosis).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Kurtosis) WarmupPeriod() int {
	r := int(C.wickra_kurtosis_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Kurtosis) IsReady() bool {
	r := bool(C.wickra_kurtosis_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Kurtosis) Name() string {
	r := C.GoString(C.wickra_kurtosis_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Kurtosis) Update(value float64) float64 {
	r := float64(C.wickra_kurtosis_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Kurtosis) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_kurtosis_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Kurtosis) Reset() {
	C.wickra_kurtosis_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Kurtosis) Close() {
	if ind.handle != nil {
		C.wickra_kurtosis_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Kvo wraps the Kvo indicator over the Wickra C ABI.
type Kvo struct {
	handle *C.struct_Kvo
}

// NewKvo constructs a Kvo. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewKvo(fast int, slow int) (*Kvo, error) {
	ptr := C.wickra_kvo_new(C.uintptr_t(fast), C.uintptr_t(slow))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Kvo{handle: ptr}
	runtime.SetFinalizer(obj, (*Kvo).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Kvo) WarmupPeriod() int {
	r := int(C.wickra_kvo_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Kvo) IsReady() bool {
	r := bool(C.wickra_kvo_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Kvo) Name() string {
	r := C.GoString(C.wickra_kvo_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Kvo) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_kvo_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Kvo) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_kvo_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Kvo) Reset() {
	C.wickra_kvo_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Kvo) Close() {
	if ind.handle != nil {
		C.wickra_kvo_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// KylesLambda wraps the KylesLambda indicator over the Wickra C ABI.
type KylesLambda struct {
	handle *C.struct_KylesLambda
}

// NewKylesLambda constructs a KylesLambda. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewKylesLambda(window int) (*KylesLambda, error) {
	ptr := C.wickra_kyles_lambda_new(C.uintptr_t(window))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &KylesLambda{handle: ptr}
	runtime.SetFinalizer(obj, (*KylesLambda).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *KylesLambda) WarmupPeriod() int {
	r := int(C.wickra_kyles_lambda_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *KylesLambda) IsReady() bool {
	r := bool(C.wickra_kyles_lambda_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *KylesLambda) Name() string {
	r := C.GoString(C.wickra_kyles_lambda_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *KylesLambda) Update(price float64, size float64, isBuy bool, timestamp int64, mid float64) float64 {
	r := float64(C.wickra_kyles_lambda_update(ind.handle, C.double(price), C.double(size), C.bool(isBuy), C.int64_t(timestamp), C.double(mid)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *KylesLambda) Reset() {
	C.wickra_kyles_lambda_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *KylesLambda) Close() {
	if ind.handle != nil {
		C.wickra_kyles_lambda_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// LadderBottom wraps the LadderBottom indicator over the Wickra C ABI.
type LadderBottom struct {
	handle *C.struct_LadderBottom
}

// NewLadderBottom constructs a LadderBottom. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewLadderBottom() (*LadderBottom, error) {
	ptr := C.wickra_ladder_bottom_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &LadderBottom{handle: ptr}
	runtime.SetFinalizer(obj, (*LadderBottom).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *LadderBottom) WarmupPeriod() int {
	r := int(C.wickra_ladder_bottom_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *LadderBottom) IsReady() bool {
	r := bool(C.wickra_ladder_bottom_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *LadderBottom) Name() string {
	r := C.GoString(C.wickra_ladder_bottom_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *LadderBottom) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_ladder_bottom_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *LadderBottom) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_ladder_bottom_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *LadderBottom) Reset() {
	C.wickra_ladder_bottom_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *LadderBottom) Close() {
	if ind.handle != nil {
		C.wickra_ladder_bottom_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// LaguerreRsi wraps the LaguerreRsi indicator over the Wickra C ABI.
type LaguerreRsi struct {
	handle *C.struct_LaguerreRsi
}

// NewLaguerreRsi constructs a LaguerreRsi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewLaguerreRsi(gamma float64) (*LaguerreRsi, error) {
	ptr := C.wickra_laguerre_rsi_new(C.double(gamma))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &LaguerreRsi{handle: ptr}
	runtime.SetFinalizer(obj, (*LaguerreRsi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *LaguerreRsi) WarmupPeriod() int {
	r := int(C.wickra_laguerre_rsi_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *LaguerreRsi) IsReady() bool {
	r := bool(C.wickra_laguerre_rsi_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *LaguerreRsi) Name() string {
	r := C.GoString(C.wickra_laguerre_rsi_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *LaguerreRsi) Update(value float64) float64 {
	r := float64(C.wickra_laguerre_rsi_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *LaguerreRsi) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_laguerre_rsi_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *LaguerreRsi) Reset() {
	C.wickra_laguerre_rsi_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *LaguerreRsi) Close() {
	if ind.handle != nil {
		C.wickra_laguerre_rsi_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// LeadLagCrossCorrelation wraps the LeadLagCrossCorrelation indicator over the Wickra C ABI.
type LeadLagCrossCorrelation struct {
	handle *C.struct_LeadLagCrossCorrelation
}

// NewLeadLagCrossCorrelation constructs a LeadLagCrossCorrelation. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewLeadLagCrossCorrelation(window int, maxLag int) (*LeadLagCrossCorrelation, error) {
	ptr := C.wickra_lead_lag_cross_correlation_new(C.uintptr_t(window), C.uintptr_t(maxLag))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &LeadLagCrossCorrelation{handle: ptr}
	runtime.SetFinalizer(obj, (*LeadLagCrossCorrelation).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *LeadLagCrossCorrelation) WarmupPeriod() int {
	r := int(C.wickra_lead_lag_cross_correlation_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *LeadLagCrossCorrelation) IsReady() bool {
	r := bool(C.wickra_lead_lag_cross_correlation_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *LeadLagCrossCorrelation) Name() string {
	r := C.GoString(C.wickra_lead_lag_cross_correlation_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *LeadLagCrossCorrelation) Update(x float64, y float64) (LeadLagCrossCorrelationOutput, bool) {
	var out C.struct_WickraLeadLagCrossCorrelationOutput
	ok := bool(C.wickra_lead_lag_cross_correlation_update(ind.handle, C.double(x), C.double(y), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return LeadLagCrossCorrelationOutput{}, false
	}
	return LeadLagCrossCorrelationOutput{int64(out.lag), float64(out.correlation)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *LeadLagCrossCorrelation) Reset() {
	C.wickra_lead_lag_cross_correlation_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *LeadLagCrossCorrelation) Close() {
	if ind.handle != nil {
		C.wickra_lead_lag_cross_correlation_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// LinRegAngle wraps the LinRegAngle indicator over the Wickra C ABI.
type LinRegAngle struct {
	handle *C.struct_LinRegAngle
}

// NewLinRegAngle constructs a LinRegAngle. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewLinRegAngle(period int) (*LinRegAngle, error) {
	ptr := C.wickra_lin_reg_angle_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &LinRegAngle{handle: ptr}
	runtime.SetFinalizer(obj, (*LinRegAngle).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *LinRegAngle) WarmupPeriod() int {
	r := int(C.wickra_lin_reg_angle_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *LinRegAngle) IsReady() bool {
	r := bool(C.wickra_lin_reg_angle_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *LinRegAngle) Name() string {
	r := C.GoString(C.wickra_lin_reg_angle_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *LinRegAngle) Update(value float64) float64 {
	r := float64(C.wickra_lin_reg_angle_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *LinRegAngle) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_lin_reg_angle_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *LinRegAngle) Reset() {
	C.wickra_lin_reg_angle_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *LinRegAngle) Close() {
	if ind.handle != nil {
		C.wickra_lin_reg_angle_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// LinRegChannel wraps the LinRegChannel indicator over the Wickra C ABI.
type LinRegChannel struct {
	handle *C.struct_LinRegChannel
}

// NewLinRegChannel constructs a LinRegChannel. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewLinRegChannel(period int, multiplier float64) (*LinRegChannel, error) {
	ptr := C.wickra_lin_reg_channel_new(C.uintptr_t(period), C.double(multiplier))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &LinRegChannel{handle: ptr}
	runtime.SetFinalizer(obj, (*LinRegChannel).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *LinRegChannel) WarmupPeriod() int {
	r := int(C.wickra_lin_reg_channel_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *LinRegChannel) IsReady() bool {
	r := bool(C.wickra_lin_reg_channel_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *LinRegChannel) Name() string {
	r := C.GoString(C.wickra_lin_reg_channel_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *LinRegChannel) Update(value float64) (LinRegChannelOutput, bool) {
	var out C.struct_WickraLinRegChannelOutput
	ok := bool(C.wickra_lin_reg_channel_update(ind.handle, C.double(value), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return LinRegChannelOutput{}, false
	}
	return LinRegChannelOutput{float64(out.upper), float64(out.middle), float64(out.lower)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *LinRegChannel) Reset() {
	C.wickra_lin_reg_channel_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *LinRegChannel) Close() {
	if ind.handle != nil {
		C.wickra_lin_reg_channel_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// LinRegIntercept wraps the LinRegIntercept indicator over the Wickra C ABI.
type LinRegIntercept struct {
	handle *C.struct_LinRegIntercept
}

// NewLinRegIntercept constructs a LinRegIntercept. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewLinRegIntercept(period int) (*LinRegIntercept, error) {
	ptr := C.wickra_lin_reg_intercept_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &LinRegIntercept{handle: ptr}
	runtime.SetFinalizer(obj, (*LinRegIntercept).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *LinRegIntercept) WarmupPeriod() int {
	r := int(C.wickra_lin_reg_intercept_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *LinRegIntercept) IsReady() bool {
	r := bool(C.wickra_lin_reg_intercept_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *LinRegIntercept) Name() string {
	r := C.GoString(C.wickra_lin_reg_intercept_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *LinRegIntercept) Update(value float64) float64 {
	r := float64(C.wickra_lin_reg_intercept_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *LinRegIntercept) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_lin_reg_intercept_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *LinRegIntercept) Reset() {
	C.wickra_lin_reg_intercept_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *LinRegIntercept) Close() {
	if ind.handle != nil {
		C.wickra_lin_reg_intercept_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// LinRegSlope wraps the LinRegSlope indicator over the Wickra C ABI.
type LinRegSlope struct {
	handle *C.struct_LinRegSlope
}

// NewLinRegSlope constructs a LinRegSlope. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewLinRegSlope(period int) (*LinRegSlope, error) {
	ptr := C.wickra_lin_reg_slope_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &LinRegSlope{handle: ptr}
	runtime.SetFinalizer(obj, (*LinRegSlope).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *LinRegSlope) WarmupPeriod() int {
	r := int(C.wickra_lin_reg_slope_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *LinRegSlope) IsReady() bool {
	r := bool(C.wickra_lin_reg_slope_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *LinRegSlope) Name() string {
	r := C.GoString(C.wickra_lin_reg_slope_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *LinRegSlope) Update(value float64) float64 {
	r := float64(C.wickra_lin_reg_slope_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *LinRegSlope) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_lin_reg_slope_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *LinRegSlope) Reset() {
	C.wickra_lin_reg_slope_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *LinRegSlope) Close() {
	if ind.handle != nil {
		C.wickra_lin_reg_slope_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// LinearRegression wraps the LinearRegression indicator over the Wickra C ABI.
type LinearRegression struct {
	handle *C.struct_LinearRegression
}

// NewLinearRegression constructs a LinearRegression. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewLinearRegression(period int) (*LinearRegression, error) {
	ptr := C.wickra_linear_regression_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &LinearRegression{handle: ptr}
	runtime.SetFinalizer(obj, (*LinearRegression).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *LinearRegression) WarmupPeriod() int {
	r := int(C.wickra_linear_regression_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *LinearRegression) IsReady() bool {
	r := bool(C.wickra_linear_regression_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *LinearRegression) Name() string {
	r := C.GoString(C.wickra_linear_regression_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *LinearRegression) Update(value float64) float64 {
	r := float64(C.wickra_linear_regression_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *LinearRegression) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_linear_regression_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *LinearRegression) Reset() {
	C.wickra_linear_regression_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *LinearRegression) Close() {
	if ind.handle != nil {
		C.wickra_linear_regression_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// LiquidationFeatures wraps the LiquidationFeatures indicator over the Wickra C ABI.
type LiquidationFeatures struct {
	handle *C.struct_LiquidationFeatures
}

// NewLiquidationFeatures constructs a LiquidationFeatures. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewLiquidationFeatures() (*LiquidationFeatures, error) {
	ptr := C.wickra_liquidation_features_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &LiquidationFeatures{handle: ptr}
	runtime.SetFinalizer(obj, (*LiquidationFeatures).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *LiquidationFeatures) WarmupPeriod() int {
	r := int(C.wickra_liquidation_features_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *LiquidationFeatures) IsReady() bool {
	r := bool(C.wickra_liquidation_features_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *LiquidationFeatures) Name() string {
	r := C.GoString(C.wickra_liquidation_features_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *LiquidationFeatures) Update(fundingRate float64, markPrice float64, indexPrice float64, futuresPrice float64, openInterest float64, longSize float64, shortSize float64, takerBuyVolume float64, takerSellVolume float64, longLiquidation float64, shortLiquidation float64, timestamp int64) (LiquidationFeaturesOutput, bool) {
	var out C.struct_WickraLiquidationFeaturesOutput
	ok := bool(C.wickra_liquidation_features_update(ind.handle, C.double(fundingRate), C.double(markPrice), C.double(indexPrice), C.double(futuresPrice), C.double(openInterest), C.double(longSize), C.double(shortSize), C.double(takerBuyVolume), C.double(takerSellVolume), C.double(longLiquidation), C.double(shortLiquidation), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return LiquidationFeaturesOutput{}, false
	}
	return LiquidationFeaturesOutput{float64(out.long_), float64(out.short_), float64(out.net), float64(out.total), float64(out.imbalance)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *LiquidationFeatures) Reset() {
	C.wickra_liquidation_features_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *LiquidationFeatures) Close() {
	if ind.handle != nil {
		C.wickra_liquidation_features_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// LogReturn wraps the LogReturn indicator over the Wickra C ABI.
type LogReturn struct {
	handle *C.struct_LogReturn
}

// NewLogReturn constructs a LogReturn. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewLogReturn(period int) (*LogReturn, error) {
	ptr := C.wickra_log_return_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &LogReturn{handle: ptr}
	runtime.SetFinalizer(obj, (*LogReturn).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *LogReturn) WarmupPeriod() int {
	r := int(C.wickra_log_return_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *LogReturn) IsReady() bool {
	r := bool(C.wickra_log_return_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *LogReturn) Name() string {
	r := C.GoString(C.wickra_log_return_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *LogReturn) Update(value float64) float64 {
	r := float64(C.wickra_log_return_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *LogReturn) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_log_return_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *LogReturn) Reset() {
	C.wickra_log_return_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *LogReturn) Close() {
	if ind.handle != nil {
		C.wickra_log_return_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// LongLeggedDoji wraps the LongLeggedDoji indicator over the Wickra C ABI.
type LongLeggedDoji struct {
	handle *C.struct_LongLeggedDoji
}

// NewLongLeggedDoji constructs a LongLeggedDoji. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewLongLeggedDoji() (*LongLeggedDoji, error) {
	ptr := C.wickra_long_legged_doji_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &LongLeggedDoji{handle: ptr}
	runtime.SetFinalizer(obj, (*LongLeggedDoji).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *LongLeggedDoji) WarmupPeriod() int {
	r := int(C.wickra_long_legged_doji_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *LongLeggedDoji) IsReady() bool {
	r := bool(C.wickra_long_legged_doji_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *LongLeggedDoji) Name() string {
	r := C.GoString(C.wickra_long_legged_doji_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *LongLeggedDoji) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_long_legged_doji_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *LongLeggedDoji) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_long_legged_doji_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *LongLeggedDoji) Reset() {
	C.wickra_long_legged_doji_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *LongLeggedDoji) Close() {
	if ind.handle != nil {
		C.wickra_long_legged_doji_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// LongLine wraps the LongLine indicator over the Wickra C ABI.
type LongLine struct {
	handle *C.struct_LongLine
}

// NewLongLine constructs a LongLine. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewLongLine() (*LongLine, error) {
	ptr := C.wickra_long_line_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &LongLine{handle: ptr}
	runtime.SetFinalizer(obj, (*LongLine).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *LongLine) WarmupPeriod() int {
	r := int(C.wickra_long_line_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *LongLine) IsReady() bool {
	r := bool(C.wickra_long_line_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *LongLine) Name() string {
	r := C.GoString(C.wickra_long_line_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *LongLine) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_long_line_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *LongLine) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_long_line_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *LongLine) Reset() {
	C.wickra_long_line_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *LongLine) Close() {
	if ind.handle != nil {
		C.wickra_long_line_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// LongShortRatio wraps the LongShortRatio indicator over the Wickra C ABI.
type LongShortRatio struct {
	handle *C.struct_LongShortRatio
}

// NewLongShortRatio constructs a LongShortRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewLongShortRatio() (*LongShortRatio, error) {
	ptr := C.wickra_long_short_ratio_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &LongShortRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*LongShortRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *LongShortRatio) WarmupPeriod() int {
	r := int(C.wickra_long_short_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *LongShortRatio) IsReady() bool {
	r := bool(C.wickra_long_short_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *LongShortRatio) Name() string {
	r := C.GoString(C.wickra_long_short_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *LongShortRatio) Update(fundingRate float64, markPrice float64, indexPrice float64, futuresPrice float64, openInterest float64, longSize float64, shortSize float64, takerBuyVolume float64, takerSellVolume float64, longLiquidation float64, shortLiquidation float64, timestamp int64) float64 {
	r := float64(C.wickra_long_short_ratio_update(ind.handle, C.double(fundingRate), C.double(markPrice), C.double(indexPrice), C.double(futuresPrice), C.double(openInterest), C.double(longSize), C.double(shortSize), C.double(takerBuyVolume), C.double(takerSellVolume), C.double(longLiquidation), C.double(shortLiquidation), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *LongShortRatio) Reset() {
	C.wickra_long_short_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *LongShortRatio) Close() {
	if ind.handle != nil {
		C.wickra_long_short_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// M2Measure wraps the M2Measure indicator over the Wickra C ABI.
type M2Measure struct {
	handle *C.struct_M2Measure
}

// NewM2Measure constructs a M2Measure. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewM2Measure(period int, riskFree float64, benchmarkStddev float64) (*M2Measure, error) {
	ptr := C.wickra_m2_measure_new(C.uintptr_t(period), C.double(riskFree), C.double(benchmarkStddev))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &M2Measure{handle: ptr}
	runtime.SetFinalizer(obj, (*M2Measure).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *M2Measure) WarmupPeriod() int {
	r := int(C.wickra_m2_measure_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *M2Measure) IsReady() bool {
	r := bool(C.wickra_m2_measure_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *M2Measure) Name() string {
	r := C.GoString(C.wickra_m2_measure_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *M2Measure) Update(value float64) float64 {
	r := float64(C.wickra_m2_measure_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *M2Measure) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_m2_measure_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *M2Measure) Reset() {
	C.wickra_m2_measure_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *M2Measure) Close() {
	if ind.handle != nil {
		C.wickra_m2_measure_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MaEnvelope wraps the MaEnvelope indicator over the Wickra C ABI.
type MaEnvelope struct {
	handle *C.struct_MaEnvelope
}

// NewMaEnvelope constructs a MaEnvelope. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMaEnvelope(period int, percent float64) (*MaEnvelope, error) {
	ptr := C.wickra_ma_envelope_new(C.uintptr_t(period), C.double(percent))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MaEnvelope{handle: ptr}
	runtime.SetFinalizer(obj, (*MaEnvelope).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MaEnvelope) WarmupPeriod() int {
	r := int(C.wickra_ma_envelope_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MaEnvelope) IsReady() bool {
	r := bool(C.wickra_ma_envelope_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MaEnvelope) Name() string {
	r := C.GoString(C.wickra_ma_envelope_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *MaEnvelope) Update(value float64) (MaEnvelopeOutput, bool) {
	var out C.struct_WickraMaEnvelopeOutput
	ok := bool(C.wickra_ma_envelope_update(ind.handle, C.double(value), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return MaEnvelopeOutput{}, false
	}
	return MaEnvelopeOutput{float64(out.upper), float64(out.middle), float64(out.lower)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MaEnvelope) Reset() {
	C.wickra_ma_envelope_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MaEnvelope) Close() {
	if ind.handle != nil {
		C.wickra_ma_envelope_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MacdExt wraps the MacdExt indicator over the Wickra C ABI.
type MacdExt struct {
	handle *C.struct_MacdExt
}

// NewMacdExt constructs a MacdExt. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMacdExt(fast int, fastType uint8, slow int, slowType uint8, signal int, signalType uint8) (*MacdExt, error) {
	ptr := C.wickra_macd_ext_new(C.uintptr_t(fast), C.uint8_t(fastType), C.uintptr_t(slow), C.uint8_t(slowType), C.uintptr_t(signal), C.uint8_t(signalType))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MacdExt{handle: ptr}
	runtime.SetFinalizer(obj, (*MacdExt).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MacdExt) WarmupPeriod() int {
	r := int(C.wickra_macd_ext_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MacdExt) IsReady() bool {
	r := bool(C.wickra_macd_ext_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MacdExt) Name() string {
	r := C.GoString(C.wickra_macd_ext_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *MacdExt) Update(value float64) (MacdOutput, bool) {
	var out C.struct_WickraMacdOutput
	ok := bool(C.wickra_macd_ext_update(ind.handle, C.double(value), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return MacdOutput{}, false
	}
	return MacdOutput{float64(out.macd), float64(out.signal), float64(out.histogram)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MacdExt) Reset() {
	C.wickra_macd_ext_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MacdExt) Close() {
	if ind.handle != nil {
		C.wickra_macd_ext_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MacdFix wraps the MacdFix indicator over the Wickra C ABI.
type MacdFix struct {
	handle *C.struct_MacdFix
}

// NewMacdFix constructs a MacdFix. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMacdFix(signal int) (*MacdFix, error) {
	ptr := C.wickra_macd_fix_new(C.uintptr_t(signal))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MacdFix{handle: ptr}
	runtime.SetFinalizer(obj, (*MacdFix).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MacdFix) WarmupPeriod() int {
	r := int(C.wickra_macd_fix_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MacdFix) IsReady() bool {
	r := bool(C.wickra_macd_fix_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MacdFix) Name() string {
	r := C.GoString(C.wickra_macd_fix_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *MacdFix) Update(value float64) (MacdOutput, bool) {
	var out C.struct_WickraMacdOutput
	ok := bool(C.wickra_macd_fix_update(ind.handle, C.double(value), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return MacdOutput{}, false
	}
	return MacdOutput{float64(out.macd), float64(out.signal), float64(out.histogram)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MacdFix) Reset() {
	C.wickra_macd_fix_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MacdFix) Close() {
	if ind.handle != nil {
		C.wickra_macd_fix_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MacdHistogram wraps the MacdHistogram indicator over the Wickra C ABI.
type MacdHistogram struct {
	handle *C.struct_MacdHistogram
}

// NewMacdHistogram constructs a MacdHistogram. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMacdHistogram(fast int, slow int, signal int) (*MacdHistogram, error) {
	ptr := C.wickra_macd_histogram_new(C.uintptr_t(fast), C.uintptr_t(slow), C.uintptr_t(signal))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MacdHistogram{handle: ptr}
	runtime.SetFinalizer(obj, (*MacdHistogram).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MacdHistogram) WarmupPeriod() int {
	r := int(C.wickra_macd_histogram_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MacdHistogram) IsReady() bool {
	r := bool(C.wickra_macd_histogram_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MacdHistogram) Name() string {
	r := C.GoString(C.wickra_macd_histogram_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *MacdHistogram) Update(value float64) float64 {
	r := float64(C.wickra_macd_histogram_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *MacdHistogram) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_macd_histogram_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MacdHistogram) Reset() {
	C.wickra_macd_histogram_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MacdHistogram) Close() {
	if ind.handle != nil {
		C.wickra_macd_histogram_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MacdIndicator wraps the MacdIndicator indicator over the Wickra C ABI.
type MacdIndicator struct {
	handle *C.struct_MacdIndicator
}

// NewMacdIndicator constructs a MacdIndicator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMacdIndicator(fast int, slow int, signal int) (*MacdIndicator, error) {
	ptr := C.wickra_macd_indicator_new(C.uintptr_t(fast), C.uintptr_t(slow), C.uintptr_t(signal))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MacdIndicator{handle: ptr}
	runtime.SetFinalizer(obj, (*MacdIndicator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MacdIndicator) WarmupPeriod() int {
	r := int(C.wickra_macd_indicator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MacdIndicator) IsReady() bool {
	r := bool(C.wickra_macd_indicator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MacdIndicator) Name() string {
	r := C.GoString(C.wickra_macd_indicator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *MacdIndicator) Update(value float64) (MacdOutput, bool) {
	var out C.struct_WickraMacdOutput
	ok := bool(C.wickra_macd_indicator_update(ind.handle, C.double(value), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return MacdOutput{}, false
	}
	return MacdOutput{float64(out.macd), float64(out.signal), float64(out.histogram)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MacdIndicator) Reset() {
	C.wickra_macd_indicator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MacdIndicator) Close() {
	if ind.handle != nil {
		C.wickra_macd_indicator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Mama wraps the Mama indicator over the Wickra C ABI.
type Mama struct {
	handle *C.struct_Mama
}

// NewMama constructs a Mama. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMama(fastLimit float64, slowLimit float64) (*Mama, error) {
	ptr := C.wickra_mama_new(C.double(fastLimit), C.double(slowLimit))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Mama{handle: ptr}
	runtime.SetFinalizer(obj, (*Mama).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Mama) WarmupPeriod() int {
	r := int(C.wickra_mama_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Mama) IsReady() bool {
	r := bool(C.wickra_mama_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Mama) Name() string {
	r := C.GoString(C.wickra_mama_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *Mama) Update(value float64) (MamaOutput, bool) {
	var out C.struct_WickraMamaOutput
	ok := bool(C.wickra_mama_update(ind.handle, C.double(value), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return MamaOutput{}, false
	}
	return MamaOutput{float64(out.mama), float64(out.fama)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Mama) Reset() {
	C.wickra_mama_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Mama) Close() {
	if ind.handle != nil {
		C.wickra_mama_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MarketFacilitationIndex wraps the MarketFacilitationIndex indicator over the Wickra C ABI.
type MarketFacilitationIndex struct {
	handle *C.struct_MarketFacilitationIndex
}

// NewMarketFacilitationIndex constructs a MarketFacilitationIndex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMarketFacilitationIndex() (*MarketFacilitationIndex, error) {
	ptr := C.wickra_market_facilitation_index_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MarketFacilitationIndex{handle: ptr}
	runtime.SetFinalizer(obj, (*MarketFacilitationIndex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MarketFacilitationIndex) WarmupPeriod() int {
	r := int(C.wickra_market_facilitation_index_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MarketFacilitationIndex) IsReady() bool {
	r := bool(C.wickra_market_facilitation_index_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MarketFacilitationIndex) Name() string {
	r := C.GoString(C.wickra_market_facilitation_index_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *MarketFacilitationIndex) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_market_facilitation_index_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *MarketFacilitationIndex) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_market_facilitation_index_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MarketFacilitationIndex) Reset() {
	C.wickra_market_facilitation_index_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MarketFacilitationIndex) Close() {
	if ind.handle != nil {
		C.wickra_market_facilitation_index_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MartinRatio wraps the MartinRatio indicator over the Wickra C ABI.
type MartinRatio struct {
	handle *C.struct_MartinRatio
}

// NewMartinRatio constructs a MartinRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMartinRatio(period int) (*MartinRatio, error) {
	ptr := C.wickra_martin_ratio_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MartinRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*MartinRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MartinRatio) WarmupPeriod() int {
	r := int(C.wickra_martin_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MartinRatio) IsReady() bool {
	r := bool(C.wickra_martin_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MartinRatio) Name() string {
	r := C.GoString(C.wickra_martin_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *MartinRatio) Update(value float64) float64 {
	r := float64(C.wickra_martin_ratio_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *MartinRatio) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_martin_ratio_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MartinRatio) Reset() {
	C.wickra_martin_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MartinRatio) Close() {
	if ind.handle != nil {
		C.wickra_martin_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Marubozu wraps the Marubozu indicator over the Wickra C ABI.
type Marubozu struct {
	handle *C.struct_Marubozu
}

// NewMarubozu constructs a Marubozu. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMarubozu() (*Marubozu, error) {
	ptr := C.wickra_marubozu_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Marubozu{handle: ptr}
	runtime.SetFinalizer(obj, (*Marubozu).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Marubozu) WarmupPeriod() int {
	r := int(C.wickra_marubozu_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Marubozu) IsReady() bool {
	r := bool(C.wickra_marubozu_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Marubozu) Name() string {
	r := C.GoString(C.wickra_marubozu_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Marubozu) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_marubozu_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Marubozu) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_marubozu_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Marubozu) Reset() {
	C.wickra_marubozu_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Marubozu) Close() {
	if ind.handle != nil {
		C.wickra_marubozu_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MassIndex wraps the MassIndex indicator over the Wickra C ABI.
type MassIndex struct {
	handle *C.struct_MassIndex
}

// NewMassIndex constructs a MassIndex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMassIndex(emaPeriod int, sumPeriod int) (*MassIndex, error) {
	ptr := C.wickra_mass_index_new(C.uintptr_t(emaPeriod), C.uintptr_t(sumPeriod))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MassIndex{handle: ptr}
	runtime.SetFinalizer(obj, (*MassIndex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MassIndex) WarmupPeriod() int {
	r := int(C.wickra_mass_index_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MassIndex) IsReady() bool {
	r := bool(C.wickra_mass_index_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MassIndex) Name() string {
	r := C.GoString(C.wickra_mass_index_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *MassIndex) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_mass_index_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *MassIndex) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_mass_index_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MassIndex) Reset() {
	C.wickra_mass_index_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MassIndex) Close() {
	if ind.handle != nil {
		C.wickra_mass_index_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MatHold wraps the MatHold indicator over the Wickra C ABI.
type MatHold struct {
	handle *C.struct_MatHold
}

// NewMatHold constructs a MatHold. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMatHold() (*MatHold, error) {
	ptr := C.wickra_mat_hold_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MatHold{handle: ptr}
	runtime.SetFinalizer(obj, (*MatHold).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MatHold) WarmupPeriod() int {
	r := int(C.wickra_mat_hold_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MatHold) IsReady() bool {
	r := bool(C.wickra_mat_hold_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MatHold) Name() string {
	r := C.GoString(C.wickra_mat_hold_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *MatHold) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_mat_hold_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *MatHold) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_mat_hold_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MatHold) Reset() {
	C.wickra_mat_hold_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MatHold) Close() {
	if ind.handle != nil {
		C.wickra_mat_hold_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MatchingLow wraps the MatchingLow indicator over the Wickra C ABI.
type MatchingLow struct {
	handle *C.struct_MatchingLow
}

// NewMatchingLow constructs a MatchingLow. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMatchingLow() (*MatchingLow, error) {
	ptr := C.wickra_matching_low_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MatchingLow{handle: ptr}
	runtime.SetFinalizer(obj, (*MatchingLow).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MatchingLow) WarmupPeriod() int {
	r := int(C.wickra_matching_low_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MatchingLow) IsReady() bool {
	r := bool(C.wickra_matching_low_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MatchingLow) Name() string {
	r := C.GoString(C.wickra_matching_low_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *MatchingLow) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_matching_low_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *MatchingLow) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_matching_low_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MatchingLow) Reset() {
	C.wickra_matching_low_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MatchingLow) Close() {
	if ind.handle != nil {
		C.wickra_matching_low_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MaxDrawdown wraps the MaxDrawdown indicator over the Wickra C ABI.
type MaxDrawdown struct {
	handle *C.struct_MaxDrawdown
}

// NewMaxDrawdown constructs a MaxDrawdown. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMaxDrawdown(period int) (*MaxDrawdown, error) {
	ptr := C.wickra_max_drawdown_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MaxDrawdown{handle: ptr}
	runtime.SetFinalizer(obj, (*MaxDrawdown).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MaxDrawdown) WarmupPeriod() int {
	r := int(C.wickra_max_drawdown_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MaxDrawdown) IsReady() bool {
	r := bool(C.wickra_max_drawdown_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MaxDrawdown) Name() string {
	r := C.GoString(C.wickra_max_drawdown_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *MaxDrawdown) Update(value float64) float64 {
	r := float64(C.wickra_max_drawdown_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *MaxDrawdown) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_max_drawdown_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MaxDrawdown) Reset() {
	C.wickra_max_drawdown_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MaxDrawdown) Close() {
	if ind.handle != nil {
		C.wickra_max_drawdown_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// McClellanOscillator wraps the McClellanOscillator indicator over the Wickra C ABI.
type McClellanOscillator struct {
	handle *C.struct_McClellanOscillator
}

// NewMcClellanOscillator constructs a McClellanOscillator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMcClellanOscillator() (*McClellanOscillator, error) {
	ptr := C.wickra_mc_clellan_oscillator_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &McClellanOscillator{handle: ptr}
	runtime.SetFinalizer(obj, (*McClellanOscillator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *McClellanOscillator) WarmupPeriod() int {
	r := int(C.wickra_mc_clellan_oscillator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *McClellanOscillator) IsReady() bool {
	r := bool(C.wickra_mc_clellan_oscillator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *McClellanOscillator) Name() string {
	r := C.GoString(C.wickra_mc_clellan_oscillator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *McClellanOscillator) Update(change []float64, volume []float64, newHigh []bool, newLow []bool, aboveMa []bool, onBuySignal []bool, timestamp int64) float64 {
	if len(volume) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newHigh) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newLow) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(aboveMa) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(onBuySignal) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_mc_clellan_oscillator_update(ind.handle, (*C.double)(unsafe.Pointer(&change[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.bool)(unsafe.Pointer(&newHigh[0])), (*C.bool)(unsafe.Pointer(&newLow[0])), (*C.bool)(unsafe.Pointer(&aboveMa[0])), (*C.bool)(unsafe.Pointer(&onBuySignal[0])), C.uintptr_t(len(change)), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(change)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(newHigh)
	runtime.KeepAlive(newLow)
	runtime.KeepAlive(aboveMa)
	runtime.KeepAlive(onBuySignal)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *McClellanOscillator) Reset() {
	C.wickra_mc_clellan_oscillator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *McClellanOscillator) Close() {
	if ind.handle != nil {
		C.wickra_mc_clellan_oscillator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// McClellanSummationIndex wraps the McClellanSummationIndex indicator over the Wickra C ABI.
type McClellanSummationIndex struct {
	handle *C.struct_McClellanSummationIndex
}

// NewMcClellanSummationIndex constructs a McClellanSummationIndex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMcClellanSummationIndex() (*McClellanSummationIndex, error) {
	ptr := C.wickra_mc_clellan_summation_index_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &McClellanSummationIndex{handle: ptr}
	runtime.SetFinalizer(obj, (*McClellanSummationIndex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *McClellanSummationIndex) WarmupPeriod() int {
	r := int(C.wickra_mc_clellan_summation_index_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *McClellanSummationIndex) IsReady() bool {
	r := bool(C.wickra_mc_clellan_summation_index_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *McClellanSummationIndex) Name() string {
	r := C.GoString(C.wickra_mc_clellan_summation_index_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *McClellanSummationIndex) Update(change []float64, volume []float64, newHigh []bool, newLow []bool, aboveMa []bool, onBuySignal []bool, timestamp int64) float64 {
	if len(volume) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newHigh) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newLow) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(aboveMa) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(onBuySignal) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_mc_clellan_summation_index_update(ind.handle, (*C.double)(unsafe.Pointer(&change[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.bool)(unsafe.Pointer(&newHigh[0])), (*C.bool)(unsafe.Pointer(&newLow[0])), (*C.bool)(unsafe.Pointer(&aboveMa[0])), (*C.bool)(unsafe.Pointer(&onBuySignal[0])), C.uintptr_t(len(change)), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(change)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(newHigh)
	runtime.KeepAlive(newLow)
	runtime.KeepAlive(aboveMa)
	runtime.KeepAlive(onBuySignal)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *McClellanSummationIndex) Reset() {
	C.wickra_mc_clellan_summation_index_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *McClellanSummationIndex) Close() {
	if ind.handle != nil {
		C.wickra_mc_clellan_summation_index_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// McGinleyDynamic wraps the McGinleyDynamic indicator over the Wickra C ABI.
type McGinleyDynamic struct {
	handle *C.struct_McGinleyDynamic
}

// NewMcGinleyDynamic constructs a McGinleyDynamic. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMcGinleyDynamic(period int) (*McGinleyDynamic, error) {
	ptr := C.wickra_mc_ginley_dynamic_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &McGinleyDynamic{handle: ptr}
	runtime.SetFinalizer(obj, (*McGinleyDynamic).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *McGinleyDynamic) WarmupPeriod() int {
	r := int(C.wickra_mc_ginley_dynamic_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *McGinleyDynamic) IsReady() bool {
	r := bool(C.wickra_mc_ginley_dynamic_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *McGinleyDynamic) Name() string {
	r := C.GoString(C.wickra_mc_ginley_dynamic_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *McGinleyDynamic) Update(value float64) float64 {
	r := float64(C.wickra_mc_ginley_dynamic_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *McGinleyDynamic) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_mc_ginley_dynamic_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *McGinleyDynamic) Reset() {
	C.wickra_mc_ginley_dynamic_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *McGinleyDynamic) Close() {
	if ind.handle != nil {
		C.wickra_mc_ginley_dynamic_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MedianAbsoluteDeviation wraps the MedianAbsoluteDeviation indicator over the Wickra C ABI.
type MedianAbsoluteDeviation struct {
	handle *C.struct_MedianAbsoluteDeviation
}

// NewMedianAbsoluteDeviation constructs a MedianAbsoluteDeviation. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMedianAbsoluteDeviation(period int) (*MedianAbsoluteDeviation, error) {
	ptr := C.wickra_median_absolute_deviation_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MedianAbsoluteDeviation{handle: ptr}
	runtime.SetFinalizer(obj, (*MedianAbsoluteDeviation).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MedianAbsoluteDeviation) WarmupPeriod() int {
	r := int(C.wickra_median_absolute_deviation_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MedianAbsoluteDeviation) IsReady() bool {
	r := bool(C.wickra_median_absolute_deviation_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MedianAbsoluteDeviation) Name() string {
	r := C.GoString(C.wickra_median_absolute_deviation_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *MedianAbsoluteDeviation) Update(value float64) float64 {
	r := float64(C.wickra_median_absolute_deviation_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *MedianAbsoluteDeviation) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_median_absolute_deviation_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MedianAbsoluteDeviation) Reset() {
	C.wickra_median_absolute_deviation_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MedianAbsoluteDeviation) Close() {
	if ind.handle != nil {
		C.wickra_median_absolute_deviation_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MedianChannel wraps the MedianChannel indicator over the Wickra C ABI.
type MedianChannel struct {
	handle *C.struct_MedianChannel
}

// NewMedianChannel constructs a MedianChannel. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMedianChannel(period int, multiplier float64) (*MedianChannel, error) {
	ptr := C.wickra_median_channel_new(C.uintptr_t(period), C.double(multiplier))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MedianChannel{handle: ptr}
	runtime.SetFinalizer(obj, (*MedianChannel).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MedianChannel) WarmupPeriod() int {
	r := int(C.wickra_median_channel_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MedianChannel) IsReady() bool {
	r := bool(C.wickra_median_channel_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MedianChannel) Name() string {
	r := C.GoString(C.wickra_median_channel_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *MedianChannel) Update(value float64) (MedianChannelOutput, bool) {
	var out C.struct_WickraMedianChannelOutput
	ok := bool(C.wickra_median_channel_update(ind.handle, C.double(value), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return MedianChannelOutput{}, false
	}
	return MedianChannelOutput{float64(out.upper), float64(out.middle), float64(out.lower)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MedianChannel) Reset() {
	C.wickra_median_channel_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MedianChannel) Close() {
	if ind.handle != nil {
		C.wickra_median_channel_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MedianMa wraps the MedianMa indicator over the Wickra C ABI.
type MedianMa struct {
	handle *C.struct_MedianMa
}

// NewMedianMa constructs a MedianMa. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMedianMa(period int) (*MedianMa, error) {
	ptr := C.wickra_median_ma_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MedianMa{handle: ptr}
	runtime.SetFinalizer(obj, (*MedianMa).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MedianMa) WarmupPeriod() int {
	r := int(C.wickra_median_ma_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MedianMa) IsReady() bool {
	r := bool(C.wickra_median_ma_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MedianMa) Name() string {
	r := C.GoString(C.wickra_median_ma_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *MedianMa) Update(value float64) float64 {
	r := float64(C.wickra_median_ma_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *MedianMa) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_median_ma_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MedianMa) Reset() {
	C.wickra_median_ma_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MedianMa) Close() {
	if ind.handle != nil {
		C.wickra_median_ma_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MedianPrice wraps the MedianPrice indicator over the Wickra C ABI.
type MedianPrice struct {
	handle *C.struct_MedianPrice
}

// NewMedianPrice constructs a MedianPrice. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMedianPrice() (*MedianPrice, error) {
	ptr := C.wickra_median_price_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MedianPrice{handle: ptr}
	runtime.SetFinalizer(obj, (*MedianPrice).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MedianPrice) WarmupPeriod() int {
	r := int(C.wickra_median_price_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MedianPrice) IsReady() bool {
	r := bool(C.wickra_median_price_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MedianPrice) Name() string {
	r := C.GoString(C.wickra_median_price_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *MedianPrice) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_median_price_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *MedianPrice) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_median_price_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MedianPrice) Reset() {
	C.wickra_median_price_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MedianPrice) Close() {
	if ind.handle != nil {
		C.wickra_median_price_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Mfi wraps the Mfi indicator over the Wickra C ABI.
type Mfi struct {
	handle *C.struct_Mfi
}

// NewMfi constructs a Mfi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMfi(period int) (*Mfi, error) {
	ptr := C.wickra_mfi_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Mfi{handle: ptr}
	runtime.SetFinalizer(obj, (*Mfi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Mfi) WarmupPeriod() int {
	r := int(C.wickra_mfi_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Mfi) IsReady() bool {
	r := bool(C.wickra_mfi_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Mfi) Name() string {
	r := C.GoString(C.wickra_mfi_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Mfi) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_mfi_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Mfi) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_mfi_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Mfi) Reset() {
	C.wickra_mfi_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Mfi) Close() {
	if ind.handle != nil {
		C.wickra_mfi_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Microprice wraps the Microprice indicator over the Wickra C ABI.
type Microprice struct {
	handle *C.struct_Microprice
}

// NewMicroprice constructs a Microprice. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMicroprice() (*Microprice, error) {
	ptr := C.wickra_microprice_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Microprice{handle: ptr}
	runtime.SetFinalizer(obj, (*Microprice).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Microprice) WarmupPeriod() int {
	r := int(C.wickra_microprice_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Microprice) IsReady() bool {
	r := bool(C.wickra_microprice_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Microprice) Name() string {
	r := C.GoString(C.wickra_microprice_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *Microprice) Update(bidPrice []float64, bidSize []float64, askPrice []float64, askSize []float64) float64 {
	if len(bidSize) != len(bidPrice) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(askSize) != len(askPrice) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_microprice_update(ind.handle, (*C.double)(unsafe.Pointer(&bidPrice[0])), (*C.double)(unsafe.Pointer(&bidSize[0])), C.uintptr_t(len(bidPrice)), (*C.double)(unsafe.Pointer(&askPrice[0])), (*C.double)(unsafe.Pointer(&askSize[0])), C.uintptr_t(len(askPrice))))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(bidPrice)
	runtime.KeepAlive(bidSize)
	runtime.KeepAlive(askPrice)
	runtime.KeepAlive(askSize)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Microprice) Reset() {
	C.wickra_microprice_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Microprice) Close() {
	if ind.handle != nil {
		C.wickra_microprice_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MidPoint wraps the MidPoint indicator over the Wickra C ABI.
type MidPoint struct {
	handle *C.struct_MidPoint
}

// NewMidPoint constructs a MidPoint. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMidPoint(period int) (*MidPoint, error) {
	ptr := C.wickra_mid_point_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MidPoint{handle: ptr}
	runtime.SetFinalizer(obj, (*MidPoint).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MidPoint) WarmupPeriod() int {
	r := int(C.wickra_mid_point_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MidPoint) IsReady() bool {
	r := bool(C.wickra_mid_point_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MidPoint) Name() string {
	r := C.GoString(C.wickra_mid_point_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *MidPoint) Update(value float64) float64 {
	r := float64(C.wickra_mid_point_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *MidPoint) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_mid_point_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MidPoint) Reset() {
	C.wickra_mid_point_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MidPoint) Close() {
	if ind.handle != nil {
		C.wickra_mid_point_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MidPrice wraps the MidPrice indicator over the Wickra C ABI.
type MidPrice struct {
	handle *C.struct_MidPrice
}

// NewMidPrice constructs a MidPrice. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMidPrice(period int) (*MidPrice, error) {
	ptr := C.wickra_mid_price_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MidPrice{handle: ptr}
	runtime.SetFinalizer(obj, (*MidPrice).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MidPrice) WarmupPeriod() int {
	r := int(C.wickra_mid_price_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MidPrice) IsReady() bool {
	r := bool(C.wickra_mid_price_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MidPrice) Name() string {
	r := C.GoString(C.wickra_mid_price_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *MidPrice) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_mid_price_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *MidPrice) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_mid_price_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MidPrice) Reset() {
	C.wickra_mid_price_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MidPrice) Close() {
	if ind.handle != nil {
		C.wickra_mid_price_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MinusDi wraps the MinusDi indicator over the Wickra C ABI.
type MinusDi struct {
	handle *C.struct_MinusDi
}

// NewMinusDi constructs a MinusDi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMinusDi(period int) (*MinusDi, error) {
	ptr := C.wickra_minus_di_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MinusDi{handle: ptr}
	runtime.SetFinalizer(obj, (*MinusDi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MinusDi) WarmupPeriod() int {
	r := int(C.wickra_minus_di_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MinusDi) IsReady() bool {
	r := bool(C.wickra_minus_di_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MinusDi) Name() string {
	r := C.GoString(C.wickra_minus_di_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *MinusDi) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_minus_di_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *MinusDi) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_minus_di_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MinusDi) Reset() {
	C.wickra_minus_di_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MinusDi) Close() {
	if ind.handle != nil {
		C.wickra_minus_di_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MinusDm wraps the MinusDm indicator over the Wickra C ABI.
type MinusDm struct {
	handle *C.struct_MinusDm
}

// NewMinusDm constructs a MinusDm. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMinusDm(period int) (*MinusDm, error) {
	ptr := C.wickra_minus_dm_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MinusDm{handle: ptr}
	runtime.SetFinalizer(obj, (*MinusDm).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MinusDm) WarmupPeriod() int {
	r := int(C.wickra_minus_dm_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MinusDm) IsReady() bool {
	r := bool(C.wickra_minus_dm_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MinusDm) Name() string {
	r := C.GoString(C.wickra_minus_dm_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *MinusDm) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_minus_dm_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *MinusDm) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_minus_dm_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MinusDm) Reset() {
	C.wickra_minus_dm_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MinusDm) Close() {
	if ind.handle != nil {
		C.wickra_minus_dm_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ModifiedMaStop wraps the ModifiedMaStop indicator over the Wickra C ABI.
type ModifiedMaStop struct {
	handle *C.struct_ModifiedMaStop
}

// NewModifiedMaStop constructs a ModifiedMaStop. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewModifiedMaStop(period int) (*ModifiedMaStop, error) {
	ptr := C.wickra_modified_ma_stop_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ModifiedMaStop{handle: ptr}
	runtime.SetFinalizer(obj, (*ModifiedMaStop).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ModifiedMaStop) WarmupPeriod() int {
	r := int(C.wickra_modified_ma_stop_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ModifiedMaStop) IsReady() bool {
	r := bool(C.wickra_modified_ma_stop_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ModifiedMaStop) Name() string {
	r := C.GoString(C.wickra_modified_ma_stop_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *ModifiedMaStop) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (ModifiedMaStopOutput, bool) {
	var out C.struct_WickraModifiedMaStopOutput
	ok := bool(C.wickra_modified_ma_stop_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return ModifiedMaStopOutput{}, false
	}
	return ModifiedMaStopOutput{float64(out.value), float64(out.direction)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ModifiedMaStop) Reset() {
	C.wickra_modified_ma_stop_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ModifiedMaStop) Close() {
	if ind.handle != nil {
		C.wickra_modified_ma_stop_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Mom wraps the Mom indicator over the Wickra C ABI.
type Mom struct {
	handle *C.struct_Mom
}

// NewMom constructs a Mom. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMom(period int) (*Mom, error) {
	ptr := C.wickra_mom_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Mom{handle: ptr}
	runtime.SetFinalizer(obj, (*Mom).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Mom) WarmupPeriod() int {
	r := int(C.wickra_mom_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Mom) IsReady() bool {
	r := bool(C.wickra_mom_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Mom) Name() string {
	r := C.GoString(C.wickra_mom_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Mom) Update(value float64) float64 {
	r := float64(C.wickra_mom_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Mom) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_mom_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Mom) Reset() {
	C.wickra_mom_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Mom) Close() {
	if ind.handle != nil {
		C.wickra_mom_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MorningDojiStar wraps the MorningDojiStar indicator over the Wickra C ABI.
type MorningDojiStar struct {
	handle *C.struct_MorningDojiStar
}

// NewMorningDojiStar constructs a MorningDojiStar. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMorningDojiStar() (*MorningDojiStar, error) {
	ptr := C.wickra_morning_doji_star_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MorningDojiStar{handle: ptr}
	runtime.SetFinalizer(obj, (*MorningDojiStar).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MorningDojiStar) WarmupPeriod() int {
	r := int(C.wickra_morning_doji_star_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MorningDojiStar) IsReady() bool {
	r := bool(C.wickra_morning_doji_star_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MorningDojiStar) Name() string {
	r := C.GoString(C.wickra_morning_doji_star_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *MorningDojiStar) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_morning_doji_star_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *MorningDojiStar) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_morning_doji_star_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MorningDojiStar) Reset() {
	C.wickra_morning_doji_star_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MorningDojiStar) Close() {
	if ind.handle != nil {
		C.wickra_morning_doji_star_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MorningEveningStar wraps the MorningEveningStar indicator over the Wickra C ABI.
type MorningEveningStar struct {
	handle *C.struct_MorningEveningStar
}

// NewMorningEveningStar constructs a MorningEveningStar. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMorningEveningStar() (*MorningEveningStar, error) {
	ptr := C.wickra_morning_evening_star_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MorningEveningStar{handle: ptr}
	runtime.SetFinalizer(obj, (*MorningEveningStar).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MorningEveningStar) WarmupPeriod() int {
	r := int(C.wickra_morning_evening_star_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MorningEveningStar) IsReady() bool {
	r := bool(C.wickra_morning_evening_star_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MorningEveningStar) Name() string {
	r := C.GoString(C.wickra_morning_evening_star_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *MorningEveningStar) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_morning_evening_star_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *MorningEveningStar) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_morning_evening_star_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MorningEveningStar) Reset() {
	C.wickra_morning_evening_star_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MorningEveningStar) Close() {
	if ind.handle != nil {
		C.wickra_morning_evening_star_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// MurreyMathLines wraps the MurreyMathLines indicator over the Wickra C ABI.
type MurreyMathLines struct {
	handle *C.struct_MurreyMathLines
}

// NewMurreyMathLines constructs a MurreyMathLines. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewMurreyMathLines(period int) (*MurreyMathLines, error) {
	ptr := C.wickra_murrey_math_lines_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &MurreyMathLines{handle: ptr}
	runtime.SetFinalizer(obj, (*MurreyMathLines).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *MurreyMathLines) WarmupPeriod() int {
	r := int(C.wickra_murrey_math_lines_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *MurreyMathLines) IsReady() bool {
	r := bool(C.wickra_murrey_math_lines_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *MurreyMathLines) Name() string {
	r := C.GoString(C.wickra_murrey_math_lines_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *MurreyMathLines) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (MurreyMathLinesOutput, bool) {
	var out C.struct_WickraMurreyMathLinesOutput
	ok := bool(C.wickra_murrey_math_lines_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return MurreyMathLinesOutput{}, false
	}
	return MurreyMathLinesOutput{float64(out.mm8_8), float64(out.mm7_8), float64(out.mm6_8), float64(out.mm5_8), float64(out.mm4_8), float64(out.mm3_8), float64(out.mm2_8), float64(out.mm1_8), float64(out.mm0_8)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *MurreyMathLines) Reset() {
	C.wickra_murrey_math_lines_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *MurreyMathLines) Close() {
	if ind.handle != nil {
		C.wickra_murrey_math_lines_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// NakedPoc wraps the NakedPoc indicator over the Wickra C ABI.
type NakedPoc struct {
	handle *C.struct_NakedPoc
}

// NewNakedPoc constructs a NakedPoc. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewNakedPoc(sessionLen int, bins int) (*NakedPoc, error) {
	ptr := C.wickra_naked_poc_new(C.uintptr_t(sessionLen), C.uintptr_t(bins))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &NakedPoc{handle: ptr}
	runtime.SetFinalizer(obj, (*NakedPoc).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *NakedPoc) WarmupPeriod() int {
	r := int(C.wickra_naked_poc_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *NakedPoc) IsReady() bool {
	r := bool(C.wickra_naked_poc_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *NakedPoc) Name() string {
	r := C.GoString(C.wickra_naked_poc_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *NakedPoc) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_naked_poc_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *NakedPoc) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_naked_poc_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *NakedPoc) Reset() {
	C.wickra_naked_poc_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *NakedPoc) Close() {
	if ind.handle != nil {
		C.wickra_naked_poc_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Natr wraps the Natr indicator over the Wickra C ABI.
type Natr struct {
	handle *C.struct_Natr
}

// NewNatr constructs a Natr. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewNatr(period int) (*Natr, error) {
	ptr := C.wickra_natr_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Natr{handle: ptr}
	runtime.SetFinalizer(obj, (*Natr).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Natr) WarmupPeriod() int {
	r := int(C.wickra_natr_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Natr) IsReady() bool {
	r := bool(C.wickra_natr_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Natr) Name() string {
	r := C.GoString(C.wickra_natr_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Natr) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_natr_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Natr) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_natr_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Natr) Reset() {
	C.wickra_natr_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Natr) Close() {
	if ind.handle != nil {
		C.wickra_natr_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// NewHighsNewLows wraps the NewHighsNewLows indicator over the Wickra C ABI.
type NewHighsNewLows struct {
	handle *C.struct_NewHighsNewLows
}

// NewNewHighsNewLows constructs a NewHighsNewLows. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewNewHighsNewLows() (*NewHighsNewLows, error) {
	ptr := C.wickra_new_highs_new_lows_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &NewHighsNewLows{handle: ptr}
	runtime.SetFinalizer(obj, (*NewHighsNewLows).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *NewHighsNewLows) WarmupPeriod() int {
	r := int(C.wickra_new_highs_new_lows_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *NewHighsNewLows) IsReady() bool {
	r := bool(C.wickra_new_highs_new_lows_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *NewHighsNewLows) Name() string {
	r := C.GoString(C.wickra_new_highs_new_lows_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *NewHighsNewLows) Update(change []float64, volume []float64, newHigh []bool, newLow []bool, aboveMa []bool, onBuySignal []bool, timestamp int64) float64 {
	if len(volume) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newHigh) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newLow) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(aboveMa) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(onBuySignal) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_new_highs_new_lows_update(ind.handle, (*C.double)(unsafe.Pointer(&change[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.bool)(unsafe.Pointer(&newHigh[0])), (*C.bool)(unsafe.Pointer(&newLow[0])), (*C.bool)(unsafe.Pointer(&aboveMa[0])), (*C.bool)(unsafe.Pointer(&onBuySignal[0])), C.uintptr_t(len(change)), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(change)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(newHigh)
	runtime.KeepAlive(newLow)
	runtime.KeepAlive(aboveMa)
	runtime.KeepAlive(onBuySignal)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *NewHighsNewLows) Reset() {
	C.wickra_new_highs_new_lows_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *NewHighsNewLows) Close() {
	if ind.handle != nil {
		C.wickra_new_highs_new_lows_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// NewPriceLines wraps the NewPriceLines indicator over the Wickra C ABI.
type NewPriceLines struct {
	handle *C.struct_NewPriceLines
}

// NewNewPriceLines constructs a NewPriceLines. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewNewPriceLines(count int) (*NewPriceLines, error) {
	ptr := C.wickra_new_price_lines_new(C.uintptr_t(count))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &NewPriceLines{handle: ptr}
	runtime.SetFinalizer(obj, (*NewPriceLines).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *NewPriceLines) WarmupPeriod() int {
	r := int(C.wickra_new_price_lines_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *NewPriceLines) IsReady() bool {
	r := bool(C.wickra_new_price_lines_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *NewPriceLines) Name() string {
	r := C.GoString(C.wickra_new_price_lines_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *NewPriceLines) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_new_price_lines_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *NewPriceLines) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_new_price_lines_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *NewPriceLines) Reset() {
	C.wickra_new_price_lines_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *NewPriceLines) Close() {
	if ind.handle != nil {
		C.wickra_new_price_lines_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Nrtr wraps the Nrtr indicator over the Wickra C ABI.
type Nrtr struct {
	handle *C.struct_Nrtr
}

// NewNrtr constructs a Nrtr. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewNrtr(pct float64) (*Nrtr, error) {
	ptr := C.wickra_nrtr_new(C.double(pct))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Nrtr{handle: ptr}
	runtime.SetFinalizer(obj, (*Nrtr).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Nrtr) WarmupPeriod() int {
	r := int(C.wickra_nrtr_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Nrtr) IsReady() bool {
	r := bool(C.wickra_nrtr_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Nrtr) Name() string {
	r := C.GoString(C.wickra_nrtr_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *Nrtr) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (NrtrOutput, bool) {
	var out C.struct_WickraNrtrOutput
	ok := bool(C.wickra_nrtr_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return NrtrOutput{}, false
	}
	return NrtrOutput{float64(out.value), float64(out.direction)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Nrtr) Reset() {
	C.wickra_nrtr_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Nrtr) Close() {
	if ind.handle != nil {
		C.wickra_nrtr_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Nvi wraps the Nvi indicator over the Wickra C ABI.
type Nvi struct {
	handle *C.struct_Nvi
}

// NewNvi constructs a Nvi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewNvi() (*Nvi, error) {
	ptr := C.wickra_nvi_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Nvi{handle: ptr}
	runtime.SetFinalizer(obj, (*Nvi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Nvi) WarmupPeriod() int {
	r := int(C.wickra_nvi_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Nvi) IsReady() bool {
	r := bool(C.wickra_nvi_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Nvi) Name() string {
	r := C.GoString(C.wickra_nvi_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Nvi) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_nvi_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Nvi) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_nvi_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Nvi) Reset() {
	C.wickra_nvi_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Nvi) Close() {
	if ind.handle != nil {
		C.wickra_nvi_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Obv wraps the Obv indicator over the Wickra C ABI.
type Obv struct {
	handle *C.struct_Obv
}

// NewObv constructs a Obv. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewObv() (*Obv, error) {
	ptr := C.wickra_obv_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Obv{handle: ptr}
	runtime.SetFinalizer(obj, (*Obv).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Obv) WarmupPeriod() int {
	r := int(C.wickra_obv_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Obv) IsReady() bool {
	r := bool(C.wickra_obv_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Obv) Name() string {
	r := C.GoString(C.wickra_obv_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Obv) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_obv_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Obv) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_obv_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Obv) Reset() {
	C.wickra_obv_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Obv) Close() {
	if ind.handle != nil {
		C.wickra_obv_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// OIPriceDivergence wraps the OIPriceDivergence indicator over the Wickra C ABI.
type OIPriceDivergence struct {
	handle *C.struct_OIPriceDivergence
}

// NewOIPriceDivergence constructs a OIPriceDivergence. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewOIPriceDivergence(window int) (*OIPriceDivergence, error) {
	ptr := C.wickra_oi_price_divergence_new(C.uintptr_t(window))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &OIPriceDivergence{handle: ptr}
	runtime.SetFinalizer(obj, (*OIPriceDivergence).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *OIPriceDivergence) WarmupPeriod() int {
	r := int(C.wickra_oi_price_divergence_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *OIPriceDivergence) IsReady() bool {
	r := bool(C.wickra_oi_price_divergence_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *OIPriceDivergence) Name() string {
	r := C.GoString(C.wickra_oi_price_divergence_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *OIPriceDivergence) Update(fundingRate float64, markPrice float64, indexPrice float64, futuresPrice float64, openInterest float64, longSize float64, shortSize float64, takerBuyVolume float64, takerSellVolume float64, longLiquidation float64, shortLiquidation float64, timestamp int64) float64 {
	r := float64(C.wickra_oi_price_divergence_update(ind.handle, C.double(fundingRate), C.double(markPrice), C.double(indexPrice), C.double(futuresPrice), C.double(openInterest), C.double(longSize), C.double(shortSize), C.double(takerBuyVolume), C.double(takerSellVolume), C.double(longLiquidation), C.double(shortLiquidation), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *OIPriceDivergence) Reset() {
	C.wickra_oi_price_divergence_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *OIPriceDivergence) Close() {
	if ind.handle != nil {
		C.wickra_oi_price_divergence_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// OiToVolumeRatio wraps the OiToVolumeRatio indicator over the Wickra C ABI.
type OiToVolumeRatio struct {
	handle *C.struct_OiToVolumeRatio
}

// NewOiToVolumeRatio constructs a OiToVolumeRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewOiToVolumeRatio() (*OiToVolumeRatio, error) {
	ptr := C.wickra_oi_to_volume_ratio_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &OiToVolumeRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*OiToVolumeRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *OiToVolumeRatio) WarmupPeriod() int {
	r := int(C.wickra_oi_to_volume_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *OiToVolumeRatio) IsReady() bool {
	r := bool(C.wickra_oi_to_volume_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *OiToVolumeRatio) Name() string {
	r := C.GoString(C.wickra_oi_to_volume_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *OiToVolumeRatio) Update(fundingRate float64, markPrice float64, indexPrice float64, futuresPrice float64, openInterest float64, longSize float64, shortSize float64, takerBuyVolume float64, takerSellVolume float64, longLiquidation float64, shortLiquidation float64, timestamp int64) float64 {
	r := float64(C.wickra_oi_to_volume_ratio_update(ind.handle, C.double(fundingRate), C.double(markPrice), C.double(indexPrice), C.double(futuresPrice), C.double(openInterest), C.double(longSize), C.double(shortSize), C.double(takerBuyVolume), C.double(takerSellVolume), C.double(longLiquidation), C.double(shortLiquidation), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *OiToVolumeRatio) Reset() {
	C.wickra_oi_to_volume_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *OiToVolumeRatio) Close() {
	if ind.handle != nil {
		C.wickra_oi_to_volume_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// OIWeighted wraps the OIWeighted indicator over the Wickra C ABI.
type OIWeighted struct {
	handle *C.struct_OIWeighted
}

// NewOIWeighted constructs a OIWeighted. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewOIWeighted() (*OIWeighted, error) {
	ptr := C.wickra_oi_weighted_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &OIWeighted{handle: ptr}
	runtime.SetFinalizer(obj, (*OIWeighted).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *OIWeighted) WarmupPeriod() int {
	r := int(C.wickra_oi_weighted_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *OIWeighted) IsReady() bool {
	r := bool(C.wickra_oi_weighted_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *OIWeighted) Name() string {
	r := C.GoString(C.wickra_oi_weighted_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *OIWeighted) Update(fundingRate float64, markPrice float64, indexPrice float64, futuresPrice float64, openInterest float64, longSize float64, shortSize float64, takerBuyVolume float64, takerSellVolume float64, longLiquidation float64, shortLiquidation float64, timestamp int64) float64 {
	r := float64(C.wickra_oi_weighted_update(ind.handle, C.double(fundingRate), C.double(markPrice), C.double(indexPrice), C.double(futuresPrice), C.double(openInterest), C.double(longSize), C.double(shortSize), C.double(takerBuyVolume), C.double(takerSellVolume), C.double(longLiquidation), C.double(shortLiquidation), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *OIWeighted) Reset() {
	C.wickra_oi_weighted_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *OIWeighted) Close() {
	if ind.handle != nil {
		C.wickra_oi_weighted_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// OmegaRatio wraps the OmegaRatio indicator over the Wickra C ABI.
type OmegaRatio struct {
	handle *C.struct_OmegaRatio
}

// NewOmegaRatio constructs a OmegaRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewOmegaRatio(period int, threshold float64) (*OmegaRatio, error) {
	ptr := C.wickra_omega_ratio_new(C.uintptr_t(period), C.double(threshold))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &OmegaRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*OmegaRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *OmegaRatio) WarmupPeriod() int {
	r := int(C.wickra_omega_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *OmegaRatio) IsReady() bool {
	r := bool(C.wickra_omega_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *OmegaRatio) Name() string {
	r := C.GoString(C.wickra_omega_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *OmegaRatio) Update(value float64) float64 {
	r := float64(C.wickra_omega_ratio_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *OmegaRatio) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_omega_ratio_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *OmegaRatio) Reset() {
	C.wickra_omega_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *OmegaRatio) Close() {
	if ind.handle != nil {
		C.wickra_omega_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// OnNeck wraps the OnNeck indicator over the Wickra C ABI.
type OnNeck struct {
	handle *C.struct_OnNeck
}

// NewOnNeck constructs a OnNeck. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewOnNeck() (*OnNeck, error) {
	ptr := C.wickra_on_neck_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &OnNeck{handle: ptr}
	runtime.SetFinalizer(obj, (*OnNeck).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *OnNeck) WarmupPeriod() int {
	r := int(C.wickra_on_neck_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *OnNeck) IsReady() bool {
	r := bool(C.wickra_on_neck_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *OnNeck) Name() string {
	r := C.GoString(C.wickra_on_neck_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *OnNeck) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_on_neck_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *OnNeck) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_on_neck_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *OnNeck) Reset() {
	C.wickra_on_neck_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *OnNeck) Close() {
	if ind.handle != nil {
		C.wickra_on_neck_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// OpenInterestDelta wraps the OpenInterestDelta indicator over the Wickra C ABI.
type OpenInterestDelta struct {
	handle *C.struct_OpenInterestDelta
}

// NewOpenInterestDelta constructs a OpenInterestDelta. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewOpenInterestDelta() (*OpenInterestDelta, error) {
	ptr := C.wickra_open_interest_delta_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &OpenInterestDelta{handle: ptr}
	runtime.SetFinalizer(obj, (*OpenInterestDelta).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *OpenInterestDelta) WarmupPeriod() int {
	r := int(C.wickra_open_interest_delta_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *OpenInterestDelta) IsReady() bool {
	r := bool(C.wickra_open_interest_delta_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *OpenInterestDelta) Name() string {
	r := C.GoString(C.wickra_open_interest_delta_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *OpenInterestDelta) Update(fundingRate float64, markPrice float64, indexPrice float64, futuresPrice float64, openInterest float64, longSize float64, shortSize float64, takerBuyVolume float64, takerSellVolume float64, longLiquidation float64, shortLiquidation float64, timestamp int64) float64 {
	r := float64(C.wickra_open_interest_delta_update(ind.handle, C.double(fundingRate), C.double(markPrice), C.double(indexPrice), C.double(futuresPrice), C.double(openInterest), C.double(longSize), C.double(shortSize), C.double(takerBuyVolume), C.double(takerSellVolume), C.double(longLiquidation), C.double(shortLiquidation), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *OpenInterestDelta) Reset() {
	C.wickra_open_interest_delta_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *OpenInterestDelta) Close() {
	if ind.handle != nil {
		C.wickra_open_interest_delta_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// OpenInterestMomentum wraps the OpenInterestMomentum indicator over the Wickra C ABI.
type OpenInterestMomentum struct {
	handle *C.struct_OpenInterestMomentum
}

// NewOpenInterestMomentum constructs a OpenInterestMomentum. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewOpenInterestMomentum(period int) (*OpenInterestMomentum, error) {
	ptr := C.wickra_open_interest_momentum_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &OpenInterestMomentum{handle: ptr}
	runtime.SetFinalizer(obj, (*OpenInterestMomentum).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *OpenInterestMomentum) WarmupPeriod() int {
	r := int(C.wickra_open_interest_momentum_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *OpenInterestMomentum) IsReady() bool {
	r := bool(C.wickra_open_interest_momentum_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *OpenInterestMomentum) Name() string {
	r := C.GoString(C.wickra_open_interest_momentum_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *OpenInterestMomentum) Update(fundingRate float64, markPrice float64, indexPrice float64, futuresPrice float64, openInterest float64, longSize float64, shortSize float64, takerBuyVolume float64, takerSellVolume float64, longLiquidation float64, shortLiquidation float64, timestamp int64) float64 {
	r := float64(C.wickra_open_interest_momentum_update(ind.handle, C.double(fundingRate), C.double(markPrice), C.double(indexPrice), C.double(futuresPrice), C.double(openInterest), C.double(longSize), C.double(shortSize), C.double(takerBuyVolume), C.double(takerSellVolume), C.double(longLiquidation), C.double(shortLiquidation), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *OpenInterestMomentum) Reset() {
	C.wickra_open_interest_momentum_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *OpenInterestMomentum) Close() {
	if ind.handle != nil {
		C.wickra_open_interest_momentum_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// OpeningMarubozu wraps the OpeningMarubozu indicator over the Wickra C ABI.
type OpeningMarubozu struct {
	handle *C.struct_OpeningMarubozu
}

// NewOpeningMarubozu constructs a OpeningMarubozu. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewOpeningMarubozu() (*OpeningMarubozu, error) {
	ptr := C.wickra_opening_marubozu_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &OpeningMarubozu{handle: ptr}
	runtime.SetFinalizer(obj, (*OpeningMarubozu).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *OpeningMarubozu) WarmupPeriod() int {
	r := int(C.wickra_opening_marubozu_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *OpeningMarubozu) IsReady() bool {
	r := bool(C.wickra_opening_marubozu_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *OpeningMarubozu) Name() string {
	r := C.GoString(C.wickra_opening_marubozu_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *OpeningMarubozu) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_opening_marubozu_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *OpeningMarubozu) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_opening_marubozu_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *OpeningMarubozu) Reset() {
	C.wickra_opening_marubozu_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *OpeningMarubozu) Close() {
	if ind.handle != nil {
		C.wickra_opening_marubozu_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// OpeningRange wraps the OpeningRange indicator over the Wickra C ABI.
type OpeningRange struct {
	handle *C.struct_OpeningRange
}

// NewOpeningRange constructs a OpeningRange. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewOpeningRange(period int) (*OpeningRange, error) {
	ptr := C.wickra_opening_range_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &OpeningRange{handle: ptr}
	runtime.SetFinalizer(obj, (*OpeningRange).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *OpeningRange) WarmupPeriod() int {
	r := int(C.wickra_opening_range_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *OpeningRange) IsReady() bool {
	r := bool(C.wickra_opening_range_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *OpeningRange) Name() string {
	r := C.GoString(C.wickra_opening_range_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *OpeningRange) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (OpeningRangeOutput, bool) {
	var out C.struct_WickraOpeningRangeOutput
	ok := bool(C.wickra_opening_range_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return OpeningRangeOutput{}, false
	}
	return OpeningRangeOutput{float64(out.high), float64(out.low), float64(out.breakout_distance)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *OpeningRange) Reset() {
	C.wickra_opening_range_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *OpeningRange) Close() {
	if ind.handle != nil {
		C.wickra_opening_range_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// OrderBookImbalanceFull wraps the OrderBookImbalanceFull indicator over the Wickra C ABI.
type OrderBookImbalanceFull struct {
	handle *C.struct_OrderBookImbalanceFull
}

// NewOrderBookImbalanceFull constructs a OrderBookImbalanceFull. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewOrderBookImbalanceFull() (*OrderBookImbalanceFull, error) {
	ptr := C.wickra_order_book_imbalance_full_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &OrderBookImbalanceFull{handle: ptr}
	runtime.SetFinalizer(obj, (*OrderBookImbalanceFull).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *OrderBookImbalanceFull) WarmupPeriod() int {
	r := int(C.wickra_order_book_imbalance_full_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *OrderBookImbalanceFull) IsReady() bool {
	r := bool(C.wickra_order_book_imbalance_full_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *OrderBookImbalanceFull) Name() string {
	r := C.GoString(C.wickra_order_book_imbalance_full_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *OrderBookImbalanceFull) Update(bidPrice []float64, bidSize []float64, askPrice []float64, askSize []float64) float64 {
	if len(bidSize) != len(bidPrice) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(askSize) != len(askPrice) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_order_book_imbalance_full_update(ind.handle, (*C.double)(unsafe.Pointer(&bidPrice[0])), (*C.double)(unsafe.Pointer(&bidSize[0])), C.uintptr_t(len(bidPrice)), (*C.double)(unsafe.Pointer(&askPrice[0])), (*C.double)(unsafe.Pointer(&askSize[0])), C.uintptr_t(len(askPrice))))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(bidPrice)
	runtime.KeepAlive(bidSize)
	runtime.KeepAlive(askPrice)
	runtime.KeepAlive(askSize)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *OrderBookImbalanceFull) Reset() {
	C.wickra_order_book_imbalance_full_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *OrderBookImbalanceFull) Close() {
	if ind.handle != nil {
		C.wickra_order_book_imbalance_full_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// OrderBookImbalanceTop1 wraps the OrderBookImbalanceTop1 indicator over the Wickra C ABI.
type OrderBookImbalanceTop1 struct {
	handle *C.struct_OrderBookImbalanceTop1
}

// NewOrderBookImbalanceTop1 constructs a OrderBookImbalanceTop1. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewOrderBookImbalanceTop1() (*OrderBookImbalanceTop1, error) {
	ptr := C.wickra_order_book_imbalance_top1_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &OrderBookImbalanceTop1{handle: ptr}
	runtime.SetFinalizer(obj, (*OrderBookImbalanceTop1).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *OrderBookImbalanceTop1) WarmupPeriod() int {
	r := int(C.wickra_order_book_imbalance_top1_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *OrderBookImbalanceTop1) IsReady() bool {
	r := bool(C.wickra_order_book_imbalance_top1_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *OrderBookImbalanceTop1) Name() string {
	r := C.GoString(C.wickra_order_book_imbalance_top1_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *OrderBookImbalanceTop1) Update(bidPrice []float64, bidSize []float64, askPrice []float64, askSize []float64) float64 {
	if len(bidSize) != len(bidPrice) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(askSize) != len(askPrice) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_order_book_imbalance_top1_update(ind.handle, (*C.double)(unsafe.Pointer(&bidPrice[0])), (*C.double)(unsafe.Pointer(&bidSize[0])), C.uintptr_t(len(bidPrice)), (*C.double)(unsafe.Pointer(&askPrice[0])), (*C.double)(unsafe.Pointer(&askSize[0])), C.uintptr_t(len(askPrice))))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(bidPrice)
	runtime.KeepAlive(bidSize)
	runtime.KeepAlive(askPrice)
	runtime.KeepAlive(askSize)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *OrderBookImbalanceTop1) Reset() {
	C.wickra_order_book_imbalance_top1_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *OrderBookImbalanceTop1) Close() {
	if ind.handle != nil {
		C.wickra_order_book_imbalance_top1_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// OrderBookImbalanceTopN wraps the OrderBookImbalanceTopN indicator over the Wickra C ABI.
type OrderBookImbalanceTopN struct {
	handle *C.struct_OrderBookImbalanceTopN
}

// NewOrderBookImbalanceTopN constructs a OrderBookImbalanceTopN. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewOrderBookImbalanceTopN(levels int) (*OrderBookImbalanceTopN, error) {
	ptr := C.wickra_order_book_imbalance_top_n_new(C.uintptr_t(levels))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &OrderBookImbalanceTopN{handle: ptr}
	runtime.SetFinalizer(obj, (*OrderBookImbalanceTopN).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *OrderBookImbalanceTopN) WarmupPeriod() int {
	r := int(C.wickra_order_book_imbalance_top_n_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *OrderBookImbalanceTopN) IsReady() bool {
	r := bool(C.wickra_order_book_imbalance_top_n_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *OrderBookImbalanceTopN) Name() string {
	r := C.GoString(C.wickra_order_book_imbalance_top_n_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *OrderBookImbalanceTopN) Update(bidPrice []float64, bidSize []float64, askPrice []float64, askSize []float64) float64 {
	if len(bidSize) != len(bidPrice) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(askSize) != len(askPrice) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_order_book_imbalance_top_n_update(ind.handle, (*C.double)(unsafe.Pointer(&bidPrice[0])), (*C.double)(unsafe.Pointer(&bidSize[0])), C.uintptr_t(len(bidPrice)), (*C.double)(unsafe.Pointer(&askPrice[0])), (*C.double)(unsafe.Pointer(&askSize[0])), C.uintptr_t(len(askPrice))))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(bidPrice)
	runtime.KeepAlive(bidSize)
	runtime.KeepAlive(askPrice)
	runtime.KeepAlive(askSize)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *OrderBookImbalanceTopN) Reset() {
	C.wickra_order_book_imbalance_top_n_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *OrderBookImbalanceTopN) Close() {
	if ind.handle != nil {
		C.wickra_order_book_imbalance_top_n_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// OrderFlowImbalance wraps the OrderFlowImbalance indicator over the Wickra C ABI.
type OrderFlowImbalance struct {
	handle *C.struct_OrderFlowImbalance
}

// NewOrderFlowImbalance constructs a OrderFlowImbalance. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewOrderFlowImbalance(period int) (*OrderFlowImbalance, error) {
	ptr := C.wickra_order_flow_imbalance_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &OrderFlowImbalance{handle: ptr}
	runtime.SetFinalizer(obj, (*OrderFlowImbalance).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *OrderFlowImbalance) WarmupPeriod() int {
	r := int(C.wickra_order_flow_imbalance_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *OrderFlowImbalance) IsReady() bool {
	r := bool(C.wickra_order_flow_imbalance_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *OrderFlowImbalance) Name() string {
	r := C.GoString(C.wickra_order_flow_imbalance_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *OrderFlowImbalance) Update(bidPrice []float64, bidSize []float64, askPrice []float64, askSize []float64) float64 {
	if len(bidSize) != len(bidPrice) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(askSize) != len(askPrice) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_order_flow_imbalance_update(ind.handle, (*C.double)(unsafe.Pointer(&bidPrice[0])), (*C.double)(unsafe.Pointer(&bidSize[0])), C.uintptr_t(len(bidPrice)), (*C.double)(unsafe.Pointer(&askPrice[0])), (*C.double)(unsafe.Pointer(&askSize[0])), C.uintptr_t(len(askPrice))))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(bidPrice)
	runtime.KeepAlive(bidSize)
	runtime.KeepAlive(askPrice)
	runtime.KeepAlive(askSize)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *OrderFlowImbalance) Reset() {
	C.wickra_order_flow_imbalance_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *OrderFlowImbalance) Close() {
	if ind.handle != nil {
		C.wickra_order_flow_imbalance_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// OuHalfLife wraps the OuHalfLife indicator over the Wickra C ABI.
type OuHalfLife struct {
	handle *C.struct_OuHalfLife
}

// NewOuHalfLife constructs a OuHalfLife. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewOuHalfLife(period int) (*OuHalfLife, error) {
	ptr := C.wickra_ou_half_life_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &OuHalfLife{handle: ptr}
	runtime.SetFinalizer(obj, (*OuHalfLife).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *OuHalfLife) WarmupPeriod() int {
	r := int(C.wickra_ou_half_life_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *OuHalfLife) IsReady() bool {
	r := bool(C.wickra_ou_half_life_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *OuHalfLife) Name() string {
	r := C.GoString(C.wickra_ou_half_life_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *OuHalfLife) Update(x float64, y float64) float64 {
	r := float64(C.wickra_ou_half_life_update(ind.handle, C.double(x), C.double(y)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *OuHalfLife) Batch(x []float64, y []float64) []float64 {
	n := len(x)
	if len(y) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_ou_half_life_batch(ind.handle, (*C.double)(unsafe.Pointer(&x[0])), (*C.double)(unsafe.Pointer(&y[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(x)
	runtime.KeepAlive(y)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *OuHalfLife) Reset() {
	C.wickra_ou_half_life_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *OuHalfLife) Close() {
	if ind.handle != nil {
		C.wickra_ou_half_life_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// OvernightGap wraps the OvernightGap indicator over the Wickra C ABI.
type OvernightGap struct {
	handle *C.struct_OvernightGap
}

// NewOvernightGap constructs a OvernightGap. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewOvernightGap(utcOffsetMinutes int32) (*OvernightGap, error) {
	ptr := C.wickra_overnight_gap_new(C.int32_t(utcOffsetMinutes))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &OvernightGap{handle: ptr}
	runtime.SetFinalizer(obj, (*OvernightGap).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *OvernightGap) WarmupPeriod() int {
	r := int(C.wickra_overnight_gap_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *OvernightGap) IsReady() bool {
	r := bool(C.wickra_overnight_gap_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *OvernightGap) Name() string {
	r := C.GoString(C.wickra_overnight_gap_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *OvernightGap) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_overnight_gap_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *OvernightGap) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_overnight_gap_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *OvernightGap) Reset() {
	C.wickra_overnight_gap_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *OvernightGap) Close() {
	if ind.handle != nil {
		C.wickra_overnight_gap_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// OvernightIntradayReturn wraps the OvernightIntradayReturn indicator over the Wickra C ABI.
type OvernightIntradayReturn struct {
	handle *C.struct_OvernightIntradayReturn
}

// NewOvernightIntradayReturn constructs a OvernightIntradayReturn. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewOvernightIntradayReturn(utcOffsetMinutes int32) (*OvernightIntradayReturn, error) {
	ptr := C.wickra_overnight_intraday_return_new(C.int32_t(utcOffsetMinutes))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &OvernightIntradayReturn{handle: ptr}
	runtime.SetFinalizer(obj, (*OvernightIntradayReturn).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *OvernightIntradayReturn) WarmupPeriod() int {
	r := int(C.wickra_overnight_intraday_return_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *OvernightIntradayReturn) IsReady() bool {
	r := bool(C.wickra_overnight_intraday_return_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *OvernightIntradayReturn) Name() string {
	r := C.GoString(C.wickra_overnight_intraday_return_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *OvernightIntradayReturn) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (OvernightIntradayReturnOutput, bool) {
	var out C.struct_WickraOvernightIntradayReturnOutput
	ok := bool(C.wickra_overnight_intraday_return_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return OvernightIntradayReturnOutput{}, false
	}
	return OvernightIntradayReturnOutput{float64(out.overnight), float64(out.intraday)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *OvernightIntradayReturn) Reset() {
	C.wickra_overnight_intraday_return_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *OvernightIntradayReturn) Close() {
	if ind.handle != nil {
		C.wickra_overnight_intraday_return_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// PainIndex wraps the PainIndex indicator over the Wickra C ABI.
type PainIndex struct {
	handle *C.struct_PainIndex
}

// NewPainIndex constructs a PainIndex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPainIndex(period int) (*PainIndex, error) {
	ptr := C.wickra_pain_index_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &PainIndex{handle: ptr}
	runtime.SetFinalizer(obj, (*PainIndex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *PainIndex) WarmupPeriod() int {
	r := int(C.wickra_pain_index_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *PainIndex) IsReady() bool {
	r := bool(C.wickra_pain_index_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *PainIndex) Name() string {
	r := C.GoString(C.wickra_pain_index_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *PainIndex) Update(value float64) float64 {
	r := float64(C.wickra_pain_index_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *PainIndex) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_pain_index_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *PainIndex) Reset() {
	C.wickra_pain_index_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *PainIndex) Close() {
	if ind.handle != nil {
		C.wickra_pain_index_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// PairSpreadZScore wraps the PairSpreadZScore indicator over the Wickra C ABI.
type PairSpreadZScore struct {
	handle *C.struct_PairSpreadZScore
}

// NewPairSpreadZScore constructs a PairSpreadZScore. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPairSpreadZScore(betaPeriod int, zPeriod int) (*PairSpreadZScore, error) {
	ptr := C.wickra_pair_spread_z_score_new(C.uintptr_t(betaPeriod), C.uintptr_t(zPeriod))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &PairSpreadZScore{handle: ptr}
	runtime.SetFinalizer(obj, (*PairSpreadZScore).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *PairSpreadZScore) WarmupPeriod() int {
	r := int(C.wickra_pair_spread_z_score_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *PairSpreadZScore) IsReady() bool {
	r := bool(C.wickra_pair_spread_z_score_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *PairSpreadZScore) Name() string {
	r := C.GoString(C.wickra_pair_spread_z_score_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *PairSpreadZScore) Update(x float64, y float64) float64 {
	r := float64(C.wickra_pair_spread_z_score_update(ind.handle, C.double(x), C.double(y)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *PairSpreadZScore) Batch(x []float64, y []float64) []float64 {
	n := len(x)
	if len(y) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_pair_spread_z_score_batch(ind.handle, (*C.double)(unsafe.Pointer(&x[0])), (*C.double)(unsafe.Pointer(&y[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(x)
	runtime.KeepAlive(y)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *PairSpreadZScore) Reset() {
	C.wickra_pair_spread_z_score_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *PairSpreadZScore) Close() {
	if ind.handle != nil {
		C.wickra_pair_spread_z_score_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// PairwiseBeta wraps the PairwiseBeta indicator over the Wickra C ABI.
type PairwiseBeta struct {
	handle *C.struct_PairwiseBeta
}

// NewPairwiseBeta constructs a PairwiseBeta. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPairwiseBeta(period int) (*PairwiseBeta, error) {
	ptr := C.wickra_pairwise_beta_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &PairwiseBeta{handle: ptr}
	runtime.SetFinalizer(obj, (*PairwiseBeta).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *PairwiseBeta) WarmupPeriod() int {
	r := int(C.wickra_pairwise_beta_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *PairwiseBeta) IsReady() bool {
	r := bool(C.wickra_pairwise_beta_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *PairwiseBeta) Name() string {
	r := C.GoString(C.wickra_pairwise_beta_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *PairwiseBeta) Update(x float64, y float64) float64 {
	r := float64(C.wickra_pairwise_beta_update(ind.handle, C.double(x), C.double(y)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *PairwiseBeta) Batch(x []float64, y []float64) []float64 {
	n := len(x)
	if len(y) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_pairwise_beta_batch(ind.handle, (*C.double)(unsafe.Pointer(&x[0])), (*C.double)(unsafe.Pointer(&y[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(x)
	runtime.KeepAlive(y)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *PairwiseBeta) Reset() {
	C.wickra_pairwise_beta_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *PairwiseBeta) Close() {
	if ind.handle != nil {
		C.wickra_pairwise_beta_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ParkinsonVolatility wraps the ParkinsonVolatility indicator over the Wickra C ABI.
type ParkinsonVolatility struct {
	handle *C.struct_ParkinsonVolatility
}

// NewParkinsonVolatility constructs a ParkinsonVolatility. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewParkinsonVolatility(period int, tradingPeriods int) (*ParkinsonVolatility, error) {
	ptr := C.wickra_parkinson_volatility_new(C.uintptr_t(period), C.uintptr_t(tradingPeriods))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ParkinsonVolatility{handle: ptr}
	runtime.SetFinalizer(obj, (*ParkinsonVolatility).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ParkinsonVolatility) WarmupPeriod() int {
	r := int(C.wickra_parkinson_volatility_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ParkinsonVolatility) IsReady() bool {
	r := bool(C.wickra_parkinson_volatility_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ParkinsonVolatility) Name() string {
	r := C.GoString(C.wickra_parkinson_volatility_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ParkinsonVolatility) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_parkinson_volatility_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ParkinsonVolatility) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_parkinson_volatility_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ParkinsonVolatility) Reset() {
	C.wickra_parkinson_volatility_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ParkinsonVolatility) Close() {
	if ind.handle != nil {
		C.wickra_parkinson_volatility_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// PearsonCorrelation wraps the PearsonCorrelation indicator over the Wickra C ABI.
type PearsonCorrelation struct {
	handle *C.struct_PearsonCorrelation
}

// NewPearsonCorrelation constructs a PearsonCorrelation. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPearsonCorrelation(period int) (*PearsonCorrelation, error) {
	ptr := C.wickra_pearson_correlation_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &PearsonCorrelation{handle: ptr}
	runtime.SetFinalizer(obj, (*PearsonCorrelation).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *PearsonCorrelation) WarmupPeriod() int {
	r := int(C.wickra_pearson_correlation_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *PearsonCorrelation) IsReady() bool {
	r := bool(C.wickra_pearson_correlation_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *PearsonCorrelation) Name() string {
	r := C.GoString(C.wickra_pearson_correlation_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *PearsonCorrelation) Update(x float64, y float64) float64 {
	r := float64(C.wickra_pearson_correlation_update(ind.handle, C.double(x), C.double(y)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *PearsonCorrelation) Batch(x []float64, y []float64) []float64 {
	n := len(x)
	if len(y) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_pearson_correlation_batch(ind.handle, (*C.double)(unsafe.Pointer(&x[0])), (*C.double)(unsafe.Pointer(&y[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(x)
	runtime.KeepAlive(y)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *PearsonCorrelation) Reset() {
	C.wickra_pearson_correlation_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *PearsonCorrelation) Close() {
	if ind.handle != nil {
		C.wickra_pearson_correlation_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// PercentAboveMa wraps the PercentAboveMa indicator over the Wickra C ABI.
type PercentAboveMa struct {
	handle *C.struct_PercentAboveMa
}

// NewPercentAboveMa constructs a PercentAboveMa. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPercentAboveMa() (*PercentAboveMa, error) {
	ptr := C.wickra_percent_above_ma_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &PercentAboveMa{handle: ptr}
	runtime.SetFinalizer(obj, (*PercentAboveMa).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *PercentAboveMa) WarmupPeriod() int {
	r := int(C.wickra_percent_above_ma_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *PercentAboveMa) IsReady() bool {
	r := bool(C.wickra_percent_above_ma_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *PercentAboveMa) Name() string {
	r := C.GoString(C.wickra_percent_above_ma_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *PercentAboveMa) Update(change []float64, volume []float64, newHigh []bool, newLow []bool, aboveMa []bool, onBuySignal []bool, timestamp int64) float64 {
	if len(volume) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newHigh) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newLow) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(aboveMa) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(onBuySignal) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_percent_above_ma_update(ind.handle, (*C.double)(unsafe.Pointer(&change[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.bool)(unsafe.Pointer(&newHigh[0])), (*C.bool)(unsafe.Pointer(&newLow[0])), (*C.bool)(unsafe.Pointer(&aboveMa[0])), (*C.bool)(unsafe.Pointer(&onBuySignal[0])), C.uintptr_t(len(change)), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(change)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(newHigh)
	runtime.KeepAlive(newLow)
	runtime.KeepAlive(aboveMa)
	runtime.KeepAlive(onBuySignal)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *PercentAboveMa) Reset() {
	C.wickra_percent_above_ma_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *PercentAboveMa) Close() {
	if ind.handle != nil {
		C.wickra_percent_above_ma_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// PercentB wraps the PercentB indicator over the Wickra C ABI.
type PercentB struct {
	handle *C.struct_PercentB
}

// NewPercentB constructs a PercentB. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPercentB(period int, multiplier float64) (*PercentB, error) {
	ptr := C.wickra_percent_b_new(C.uintptr_t(period), C.double(multiplier))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &PercentB{handle: ptr}
	runtime.SetFinalizer(obj, (*PercentB).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *PercentB) WarmupPeriod() int {
	r := int(C.wickra_percent_b_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *PercentB) IsReady() bool {
	r := bool(C.wickra_percent_b_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *PercentB) Name() string {
	r := C.GoString(C.wickra_percent_b_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *PercentB) Update(value float64) float64 {
	r := float64(C.wickra_percent_b_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *PercentB) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_percent_b_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *PercentB) Reset() {
	C.wickra_percent_b_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *PercentB) Close() {
	if ind.handle != nil {
		C.wickra_percent_b_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// PercentageTrailingStop wraps the PercentageTrailingStop indicator over the Wickra C ABI.
type PercentageTrailingStop struct {
	handle *C.struct_PercentageTrailingStop
}

// NewPercentageTrailingStop constructs a PercentageTrailingStop. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPercentageTrailingStop(percent float64) (*PercentageTrailingStop, error) {
	ptr := C.wickra_percentage_trailing_stop_new(C.double(percent))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &PercentageTrailingStop{handle: ptr}
	runtime.SetFinalizer(obj, (*PercentageTrailingStop).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *PercentageTrailingStop) WarmupPeriod() int {
	r := int(C.wickra_percentage_trailing_stop_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *PercentageTrailingStop) IsReady() bool {
	r := bool(C.wickra_percentage_trailing_stop_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *PercentageTrailingStop) Name() string {
	r := C.GoString(C.wickra_percentage_trailing_stop_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *PercentageTrailingStop) Update(value float64) float64 {
	r := float64(C.wickra_percentage_trailing_stop_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *PercentageTrailingStop) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_percentage_trailing_stop_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *PercentageTrailingStop) Reset() {
	C.wickra_percentage_trailing_stop_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *PercentageTrailingStop) Close() {
	if ind.handle != nil {
		C.wickra_percentage_trailing_stop_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// PerpetualPremiumIndex wraps the PerpetualPremiumIndex indicator over the Wickra C ABI.
type PerpetualPremiumIndex struct {
	handle *C.struct_PerpetualPremiumIndex
}

// NewPerpetualPremiumIndex constructs a PerpetualPremiumIndex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPerpetualPremiumIndex() (*PerpetualPremiumIndex, error) {
	ptr := C.wickra_perpetual_premium_index_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &PerpetualPremiumIndex{handle: ptr}
	runtime.SetFinalizer(obj, (*PerpetualPremiumIndex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *PerpetualPremiumIndex) WarmupPeriod() int {
	r := int(C.wickra_perpetual_premium_index_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *PerpetualPremiumIndex) IsReady() bool {
	r := bool(C.wickra_perpetual_premium_index_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *PerpetualPremiumIndex) Name() string {
	r := C.GoString(C.wickra_perpetual_premium_index_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *PerpetualPremiumIndex) Update(fundingRate float64, markPrice float64, indexPrice float64, futuresPrice float64, openInterest float64, longSize float64, shortSize float64, takerBuyVolume float64, takerSellVolume float64, longLiquidation float64, shortLiquidation float64, timestamp int64) float64 {
	r := float64(C.wickra_perpetual_premium_index_update(ind.handle, C.double(fundingRate), C.double(markPrice), C.double(indexPrice), C.double(futuresPrice), C.double(openInterest), C.double(longSize), C.double(shortSize), C.double(takerBuyVolume), C.double(takerSellVolume), C.double(longLiquidation), C.double(shortLiquidation), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *PerpetualPremiumIndex) Reset() {
	C.wickra_perpetual_premium_index_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *PerpetualPremiumIndex) Close() {
	if ind.handle != nil {
		C.wickra_perpetual_premium_index_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Pgo wraps the Pgo indicator over the Wickra C ABI.
type Pgo struct {
	handle *C.struct_Pgo
}

// NewPgo constructs a Pgo. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPgo(period int) (*Pgo, error) {
	ptr := C.wickra_pgo_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Pgo{handle: ptr}
	runtime.SetFinalizer(obj, (*Pgo).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Pgo) WarmupPeriod() int {
	r := int(C.wickra_pgo_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Pgo) IsReady() bool {
	r := bool(C.wickra_pgo_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Pgo) Name() string {
	r := C.GoString(C.wickra_pgo_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Pgo) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_pgo_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Pgo) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_pgo_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Pgo) Reset() {
	C.wickra_pgo_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Pgo) Close() {
	if ind.handle != nil {
		C.wickra_pgo_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// PiercingDarkCloud wraps the PiercingDarkCloud indicator over the Wickra C ABI.
type PiercingDarkCloud struct {
	handle *C.struct_PiercingDarkCloud
}

// NewPiercingDarkCloud constructs a PiercingDarkCloud. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPiercingDarkCloud() (*PiercingDarkCloud, error) {
	ptr := C.wickra_piercing_dark_cloud_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &PiercingDarkCloud{handle: ptr}
	runtime.SetFinalizer(obj, (*PiercingDarkCloud).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *PiercingDarkCloud) WarmupPeriod() int {
	r := int(C.wickra_piercing_dark_cloud_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *PiercingDarkCloud) IsReady() bool {
	r := bool(C.wickra_piercing_dark_cloud_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *PiercingDarkCloud) Name() string {
	r := C.GoString(C.wickra_piercing_dark_cloud_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *PiercingDarkCloud) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_piercing_dark_cloud_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *PiercingDarkCloud) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_piercing_dark_cloud_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *PiercingDarkCloud) Reset() {
	C.wickra_piercing_dark_cloud_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *PiercingDarkCloud) Close() {
	if ind.handle != nil {
		C.wickra_piercing_dark_cloud_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Pin wraps the Pin indicator over the Wickra C ABI.
type Pin struct {
	handle *C.struct_Pin
}

// NewPin constructs a Pin. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPin(window int) (*Pin, error) {
	ptr := C.wickra_pin_new(C.uintptr_t(window))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Pin{handle: ptr}
	runtime.SetFinalizer(obj, (*Pin).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Pin) WarmupPeriod() int {
	r := int(C.wickra_pin_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Pin) IsReady() bool {
	r := bool(C.wickra_pin_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Pin) Name() string {
	r := C.GoString(C.wickra_pin_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Pin) Update(price float64, size float64, isBuy bool, timestamp int64) float64 {
	r := float64(C.wickra_pin_update(ind.handle, C.double(price), C.double(size), C.bool(isBuy), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Pin) Reset() {
	C.wickra_pin_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Pin) Close() {
	if ind.handle != nil {
		C.wickra_pin_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// PivotReversal wraps the PivotReversal indicator over the Wickra C ABI.
type PivotReversal struct {
	handle *C.struct_PivotReversal
}

// NewPivotReversal constructs a PivotReversal. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPivotReversal(left int, right int) (*PivotReversal, error) {
	ptr := C.wickra_pivot_reversal_new(C.uintptr_t(left), C.uintptr_t(right))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &PivotReversal{handle: ptr}
	runtime.SetFinalizer(obj, (*PivotReversal).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *PivotReversal) WarmupPeriod() int {
	r := int(C.wickra_pivot_reversal_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *PivotReversal) IsReady() bool {
	r := bool(C.wickra_pivot_reversal_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *PivotReversal) Name() string {
	r := C.GoString(C.wickra_pivot_reversal_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *PivotReversal) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_pivot_reversal_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *PivotReversal) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_pivot_reversal_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *PivotReversal) Reset() {
	C.wickra_pivot_reversal_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *PivotReversal) Close() {
	if ind.handle != nil {
		C.wickra_pivot_reversal_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// PlusDi wraps the PlusDi indicator over the Wickra C ABI.
type PlusDi struct {
	handle *C.struct_PlusDi
}

// NewPlusDi constructs a PlusDi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPlusDi(period int) (*PlusDi, error) {
	ptr := C.wickra_plus_di_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &PlusDi{handle: ptr}
	runtime.SetFinalizer(obj, (*PlusDi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *PlusDi) WarmupPeriod() int {
	r := int(C.wickra_plus_di_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *PlusDi) IsReady() bool {
	r := bool(C.wickra_plus_di_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *PlusDi) Name() string {
	r := C.GoString(C.wickra_plus_di_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *PlusDi) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_plus_di_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *PlusDi) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_plus_di_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *PlusDi) Reset() {
	C.wickra_plus_di_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *PlusDi) Close() {
	if ind.handle != nil {
		C.wickra_plus_di_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// PlusDm wraps the PlusDm indicator over the Wickra C ABI.
type PlusDm struct {
	handle *C.struct_PlusDm
}

// NewPlusDm constructs a PlusDm. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPlusDm(period int) (*PlusDm, error) {
	ptr := C.wickra_plus_dm_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &PlusDm{handle: ptr}
	runtime.SetFinalizer(obj, (*PlusDm).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *PlusDm) WarmupPeriod() int {
	r := int(C.wickra_plus_dm_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *PlusDm) IsReady() bool {
	r := bool(C.wickra_plus_dm_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *PlusDm) Name() string {
	r := C.GoString(C.wickra_plus_dm_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *PlusDm) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_plus_dm_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *PlusDm) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_plus_dm_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *PlusDm) Reset() {
	C.wickra_plus_dm_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *PlusDm) Close() {
	if ind.handle != nil {
		C.wickra_plus_dm_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Pmo wraps the Pmo indicator over the Wickra C ABI.
type Pmo struct {
	handle *C.struct_Pmo
}

// NewPmo constructs a Pmo. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPmo(smoothing1 int, smoothing2 int) (*Pmo, error) {
	ptr := C.wickra_pmo_new(C.uintptr_t(smoothing1), C.uintptr_t(smoothing2))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Pmo{handle: ptr}
	runtime.SetFinalizer(obj, (*Pmo).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Pmo) WarmupPeriod() int {
	r := int(C.wickra_pmo_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Pmo) IsReady() bool {
	r := bool(C.wickra_pmo_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Pmo) Name() string {
	r := C.GoString(C.wickra_pmo_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Pmo) Update(value float64) float64 {
	r := float64(C.wickra_pmo_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Pmo) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_pmo_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Pmo) Reset() {
	C.wickra_pmo_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Pmo) Close() {
	if ind.handle != nil {
		C.wickra_pmo_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// PointAndFigureBars wraps the PointAndFigureBars indicator over the Wickra C ABI.
type PointAndFigureBars struct {
	handle *C.struct_PointAndFigureBars
}

// NewPointAndFigureBars constructs a PointAndFigureBars. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPointAndFigureBars(boxSize float64, reversal int) (*PointAndFigureBars, error) {
	ptr := C.wickra_point_and_figure_bars_new(C.double(boxSize), C.uintptr_t(reversal))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &PointAndFigureBars{handle: ptr}
	runtime.SetFinalizer(obj, (*PointAndFigureBars).Close)
	return obj, nil
}

// Name returns the indicator's canonical name.
func (ind *PointAndFigureBars) Name() string {
	r := C.GoString(C.wickra_point_and_figure_bars_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one candle and returns any bars completed by it
// (a single candle may complete several).
func (ind *PointAndFigureBars) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) []PnfColumn {
	const capacity = 64
	var buf [capacity]C.struct_WickraPnfColumn
	n := int(C.wickra_point_and_figure_bars_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &buf[0], C.uintptr_t(capacity)))
	runtime.KeepAlive(ind)
	if n <= 0 {
		return nil
	}
	out := make([]PnfColumn, n)
	for i := 0; i < n; i++ {
		out[i] = PnfColumn{int8(buf[i].direction), float64(buf[i].high), float64(buf[i].low)}
	}
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *PointAndFigureBars) Reset() {
	C.wickra_point_and_figure_bars_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *PointAndFigureBars) Close() {
	if ind.handle != nil {
		C.wickra_point_and_figure_bars_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// PolarizedFractalEfficiency wraps the PolarizedFractalEfficiency indicator over the Wickra C ABI.
type PolarizedFractalEfficiency struct {
	handle *C.struct_PolarizedFractalEfficiency
}

// NewPolarizedFractalEfficiency constructs a PolarizedFractalEfficiency. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPolarizedFractalEfficiency(period int, smoothing int) (*PolarizedFractalEfficiency, error) {
	ptr := C.wickra_polarized_fractal_efficiency_new(C.uintptr_t(period), C.uintptr_t(smoothing))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &PolarizedFractalEfficiency{handle: ptr}
	runtime.SetFinalizer(obj, (*PolarizedFractalEfficiency).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *PolarizedFractalEfficiency) WarmupPeriod() int {
	r := int(C.wickra_polarized_fractal_efficiency_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *PolarizedFractalEfficiency) IsReady() bool {
	r := bool(C.wickra_polarized_fractal_efficiency_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *PolarizedFractalEfficiency) Name() string {
	r := C.GoString(C.wickra_polarized_fractal_efficiency_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *PolarizedFractalEfficiency) Update(value float64) float64 {
	r := float64(C.wickra_polarized_fractal_efficiency_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *PolarizedFractalEfficiency) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_polarized_fractal_efficiency_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *PolarizedFractalEfficiency) Reset() {
	C.wickra_polarized_fractal_efficiency_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *PolarizedFractalEfficiency) Close() {
	if ind.handle != nil {
		C.wickra_polarized_fractal_efficiency_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Ppo wraps the Ppo indicator over the Wickra C ABI.
type Ppo struct {
	handle *C.struct_Ppo
}

// NewPpo constructs a Ppo. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPpo(fast int, slow int) (*Ppo, error) {
	ptr := C.wickra_ppo_new(C.uintptr_t(fast), C.uintptr_t(slow))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Ppo{handle: ptr}
	runtime.SetFinalizer(obj, (*Ppo).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Ppo) WarmupPeriod() int {
	r := int(C.wickra_ppo_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Ppo) IsReady() bool {
	r := bool(C.wickra_ppo_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Ppo) Name() string {
	r := C.GoString(C.wickra_ppo_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Ppo) Update(value float64) float64 {
	r := float64(C.wickra_ppo_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Ppo) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_ppo_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Ppo) Reset() {
	C.wickra_ppo_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Ppo) Close() {
	if ind.handle != nil {
		C.wickra_ppo_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// PpoHistogram wraps the PpoHistogram indicator over the Wickra C ABI.
type PpoHistogram struct {
	handle *C.struct_PpoHistogram
}

// NewPpoHistogram constructs a PpoHistogram. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPpoHistogram(fast int, slow int, signal int) (*PpoHistogram, error) {
	ptr := C.wickra_ppo_histogram_new(C.uintptr_t(fast), C.uintptr_t(slow), C.uintptr_t(signal))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &PpoHistogram{handle: ptr}
	runtime.SetFinalizer(obj, (*PpoHistogram).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *PpoHistogram) WarmupPeriod() int {
	r := int(C.wickra_ppo_histogram_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *PpoHistogram) IsReady() bool {
	r := bool(C.wickra_ppo_histogram_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *PpoHistogram) Name() string {
	r := C.GoString(C.wickra_ppo_histogram_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *PpoHistogram) Update(value float64) float64 {
	r := float64(C.wickra_ppo_histogram_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *PpoHistogram) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_ppo_histogram_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *PpoHistogram) Reset() {
	C.wickra_ppo_histogram_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *PpoHistogram) Close() {
	if ind.handle != nil {
		C.wickra_ppo_histogram_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ProfileShape wraps the ProfileShape indicator over the Wickra C ABI.
type ProfileShape struct {
	handle *C.struct_ProfileShape
}

// NewProfileShape constructs a ProfileShape. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewProfileShape(period int, bins int) (*ProfileShape, error) {
	ptr := C.wickra_profile_shape_new(C.uintptr_t(period), C.uintptr_t(bins))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ProfileShape{handle: ptr}
	runtime.SetFinalizer(obj, (*ProfileShape).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ProfileShape) WarmupPeriod() int {
	r := int(C.wickra_profile_shape_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ProfileShape) IsReady() bool {
	r := bool(C.wickra_profile_shape_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ProfileShape) Name() string {
	r := C.GoString(C.wickra_profile_shape_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ProfileShape) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_profile_shape_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ProfileShape) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_profile_shape_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ProfileShape) Reset() {
	C.wickra_profile_shape_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ProfileShape) Close() {
	if ind.handle != nil {
		C.wickra_profile_shape_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ProfitFactor wraps the ProfitFactor indicator over the Wickra C ABI.
type ProfitFactor struct {
	handle *C.struct_ProfitFactor
}

// NewProfitFactor constructs a ProfitFactor. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewProfitFactor(period int) (*ProfitFactor, error) {
	ptr := C.wickra_profit_factor_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ProfitFactor{handle: ptr}
	runtime.SetFinalizer(obj, (*ProfitFactor).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ProfitFactor) WarmupPeriod() int {
	r := int(C.wickra_profit_factor_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ProfitFactor) IsReady() bool {
	r := bool(C.wickra_profit_factor_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ProfitFactor) Name() string {
	r := C.GoString(C.wickra_profit_factor_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ProfitFactor) Update(value float64) float64 {
	r := float64(C.wickra_profit_factor_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ProfitFactor) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_profit_factor_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ProfitFactor) Reset() {
	C.wickra_profit_factor_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ProfitFactor) Close() {
	if ind.handle != nil {
		C.wickra_profit_factor_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ProjectionBands wraps the ProjectionBands indicator over the Wickra C ABI.
type ProjectionBands struct {
	handle *C.struct_ProjectionBands
}

// NewProjectionBands constructs a ProjectionBands. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewProjectionBands(period int) (*ProjectionBands, error) {
	ptr := C.wickra_projection_bands_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ProjectionBands{handle: ptr}
	runtime.SetFinalizer(obj, (*ProjectionBands).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ProjectionBands) WarmupPeriod() int {
	r := int(C.wickra_projection_bands_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ProjectionBands) IsReady() bool {
	r := bool(C.wickra_projection_bands_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ProjectionBands) Name() string {
	r := C.GoString(C.wickra_projection_bands_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *ProjectionBands) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (ProjectionBandsOutput, bool) {
	var out C.struct_WickraProjectionBandsOutput
	ok := bool(C.wickra_projection_bands_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return ProjectionBandsOutput{}, false
	}
	return ProjectionBandsOutput{float64(out.upper), float64(out.middle), float64(out.lower)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ProjectionBands) Reset() {
	C.wickra_projection_bands_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ProjectionBands) Close() {
	if ind.handle != nil {
		C.wickra_projection_bands_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ProjectionOscillator wraps the ProjectionOscillator indicator over the Wickra C ABI.
type ProjectionOscillator struct {
	handle *C.struct_ProjectionOscillator
}

// NewProjectionOscillator constructs a ProjectionOscillator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewProjectionOscillator(period int) (*ProjectionOscillator, error) {
	ptr := C.wickra_projection_oscillator_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ProjectionOscillator{handle: ptr}
	runtime.SetFinalizer(obj, (*ProjectionOscillator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ProjectionOscillator) WarmupPeriod() int {
	r := int(C.wickra_projection_oscillator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ProjectionOscillator) IsReady() bool {
	r := bool(C.wickra_projection_oscillator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ProjectionOscillator) Name() string {
	r := C.GoString(C.wickra_projection_oscillator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ProjectionOscillator) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_projection_oscillator_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ProjectionOscillator) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_projection_oscillator_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ProjectionOscillator) Reset() {
	C.wickra_projection_oscillator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ProjectionOscillator) Close() {
	if ind.handle != nil {
		C.wickra_projection_oscillator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Psar wraps the Psar indicator over the Wickra C ABI.
type Psar struct {
	handle *C.struct_Psar
}

// NewPsar constructs a Psar. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPsar(afStart float64, afStep float64, afMax float64) (*Psar, error) {
	ptr := C.wickra_psar_new(C.double(afStart), C.double(afStep), C.double(afMax))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Psar{handle: ptr}
	runtime.SetFinalizer(obj, (*Psar).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Psar) WarmupPeriod() int {
	r := int(C.wickra_psar_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Psar) IsReady() bool {
	r := bool(C.wickra_psar_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Psar) Name() string {
	r := C.GoString(C.wickra_psar_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Psar) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_psar_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Psar) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_psar_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Psar) Reset() {
	C.wickra_psar_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Psar) Close() {
	if ind.handle != nil {
		C.wickra_psar_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Pvi wraps the Pvi indicator over the Wickra C ABI.
type Pvi struct {
	handle *C.struct_Pvi
}

// NewPvi constructs a Pvi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewPvi() (*Pvi, error) {
	ptr := C.wickra_pvi_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Pvi{handle: ptr}
	runtime.SetFinalizer(obj, (*Pvi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Pvi) WarmupPeriod() int {
	r := int(C.wickra_pvi_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Pvi) IsReady() bool {
	r := bool(C.wickra_pvi_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Pvi) Name() string {
	r := C.GoString(C.wickra_pvi_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Pvi) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_pvi_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Pvi) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_pvi_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Pvi) Reset() {
	C.wickra_pvi_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Pvi) Close() {
	if ind.handle != nil {
		C.wickra_pvi_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Qqe wraps the Qqe indicator over the Wickra C ABI.
type Qqe struct {
	handle *C.struct_Qqe
}

// NewQqe constructs a Qqe. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewQqe(rsiPeriod int, smoothing int, factor float64) (*Qqe, error) {
	ptr := C.wickra_qqe_new(C.uintptr_t(rsiPeriod), C.uintptr_t(smoothing), C.double(factor))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Qqe{handle: ptr}
	runtime.SetFinalizer(obj, (*Qqe).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Qqe) WarmupPeriod() int {
	r := int(C.wickra_qqe_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Qqe) IsReady() bool {
	r := bool(C.wickra_qqe_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Qqe) Name() string {
	r := C.GoString(C.wickra_qqe_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *Qqe) Update(value float64) (QqeOutput, bool) {
	var out C.struct_WickraQqeOutput
	ok := bool(C.wickra_qqe_update(ind.handle, C.double(value), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return QqeOutput{}, false
	}
	return QqeOutput{float64(out.rsi_ma), float64(out.trailing_line)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Qqe) Reset() {
	C.wickra_qqe_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Qqe) Close() {
	if ind.handle != nil {
		C.wickra_qqe_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Qstick wraps the Qstick indicator over the Wickra C ABI.
type Qstick struct {
	handle *C.struct_Qstick
}

// NewQstick constructs a Qstick. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewQstick(period int) (*Qstick, error) {
	ptr := C.wickra_qstick_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Qstick{handle: ptr}
	runtime.SetFinalizer(obj, (*Qstick).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Qstick) WarmupPeriod() int {
	r := int(C.wickra_qstick_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Qstick) IsReady() bool {
	r := bool(C.wickra_qstick_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Qstick) Name() string {
	r := C.GoString(C.wickra_qstick_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Qstick) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_qstick_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Qstick) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_qstick_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Qstick) Reset() {
	C.wickra_qstick_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Qstick) Close() {
	if ind.handle != nil {
		C.wickra_qstick_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// QuartileBands wraps the QuartileBands indicator over the Wickra C ABI.
type QuartileBands struct {
	handle *C.struct_QuartileBands
}

// NewQuartileBands constructs a QuartileBands. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewQuartileBands(period int) (*QuartileBands, error) {
	ptr := C.wickra_quartile_bands_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &QuartileBands{handle: ptr}
	runtime.SetFinalizer(obj, (*QuartileBands).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *QuartileBands) WarmupPeriod() int {
	r := int(C.wickra_quartile_bands_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *QuartileBands) IsReady() bool {
	r := bool(C.wickra_quartile_bands_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *QuartileBands) Name() string {
	r := C.GoString(C.wickra_quartile_bands_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *QuartileBands) Update(value float64) (QuartileBandsOutput, bool) {
	var out C.struct_WickraQuartileBandsOutput
	ok := bool(C.wickra_quartile_bands_update(ind.handle, C.double(value), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return QuartileBandsOutput{}, false
	}
	return QuartileBandsOutput{float64(out.upper), float64(out.middle), float64(out.lower)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *QuartileBands) Reset() {
	C.wickra_quartile_bands_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *QuartileBands) Close() {
	if ind.handle != nil {
		C.wickra_quartile_bands_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// QuotedSpread wraps the QuotedSpread indicator over the Wickra C ABI.
type QuotedSpread struct {
	handle *C.struct_QuotedSpread
}

// NewQuotedSpread constructs a QuotedSpread. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewQuotedSpread() (*QuotedSpread, error) {
	ptr := C.wickra_quoted_spread_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &QuotedSpread{handle: ptr}
	runtime.SetFinalizer(obj, (*QuotedSpread).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *QuotedSpread) WarmupPeriod() int {
	r := int(C.wickra_quoted_spread_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *QuotedSpread) IsReady() bool {
	r := bool(C.wickra_quoted_spread_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *QuotedSpread) Name() string {
	r := C.GoString(C.wickra_quoted_spread_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *QuotedSpread) Update(bidPrice []float64, bidSize []float64, askPrice []float64, askSize []float64) float64 {
	if len(bidSize) != len(bidPrice) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(askSize) != len(askPrice) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_quoted_spread_update(ind.handle, (*C.double)(unsafe.Pointer(&bidPrice[0])), (*C.double)(unsafe.Pointer(&bidSize[0])), C.uintptr_t(len(bidPrice)), (*C.double)(unsafe.Pointer(&askPrice[0])), (*C.double)(unsafe.Pointer(&askSize[0])), C.uintptr_t(len(askPrice))))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(bidPrice)
	runtime.KeepAlive(bidSize)
	runtime.KeepAlive(askPrice)
	runtime.KeepAlive(askSize)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *QuotedSpread) Reset() {
	C.wickra_quoted_spread_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *QuotedSpread) Close() {
	if ind.handle != nil {
		C.wickra_quoted_spread_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RSquared wraps the RSquared indicator over the Wickra C ABI.
type RSquared struct {
	handle *C.struct_RSquared
}

// NewRSquared constructs a RSquared. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRSquared(period int) (*RSquared, error) {
	ptr := C.wickra_r_squared_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RSquared{handle: ptr}
	runtime.SetFinalizer(obj, (*RSquared).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RSquared) WarmupPeriod() int {
	r := int(C.wickra_r_squared_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RSquared) IsReady() bool {
	r := bool(C.wickra_r_squared_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RSquared) Name() string {
	r := C.GoString(C.wickra_r_squared_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RSquared) Update(value float64) float64 {
	r := float64(C.wickra_r_squared_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *RSquared) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_r_squared_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RSquared) Reset() {
	C.wickra_r_squared_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RSquared) Close() {
	if ind.handle != nil {
		C.wickra_r_squared_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RangeBars wraps the RangeBars indicator over the Wickra C ABI.
type RangeBars struct {
	handle *C.struct_RangeBars
}

// NewRangeBars constructs a RangeBars. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRangeBars(range_ float64) (*RangeBars, error) {
	ptr := C.wickra_range_bars_new(C.double(range_))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RangeBars{handle: ptr}
	runtime.SetFinalizer(obj, (*RangeBars).Close)
	return obj, nil
}

// Name returns the indicator's canonical name.
func (ind *RangeBars) Name() string {
	r := C.GoString(C.wickra_range_bars_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one candle and returns any bars completed by it
// (a single candle may complete several).
func (ind *RangeBars) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) []RangeBar {
	const capacity = 64
	var buf [capacity]C.struct_WickraRangeBar
	n := int(C.wickra_range_bars_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &buf[0], C.uintptr_t(capacity)))
	runtime.KeepAlive(ind)
	if n <= 0 {
		return nil
	}
	out := make([]RangeBar, n)
	for i := 0; i < n; i++ {
		out[i] = RangeBar{float64(buf[i].open), float64(buf[i].close), int8(buf[i].direction)}
	}
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RangeBars) Reset() {
	C.wickra_range_bars_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RangeBars) Close() {
	if ind.handle != nil {
		C.wickra_range_bars_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RealizedSpread wraps the RealizedSpread indicator over the Wickra C ABI.
type RealizedSpread struct {
	handle *C.struct_RealizedSpread
}

// NewRealizedSpread constructs a RealizedSpread. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRealizedSpread(horizon int) (*RealizedSpread, error) {
	ptr := C.wickra_realized_spread_new(C.uintptr_t(horizon))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RealizedSpread{handle: ptr}
	runtime.SetFinalizer(obj, (*RealizedSpread).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RealizedSpread) WarmupPeriod() int {
	r := int(C.wickra_realized_spread_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RealizedSpread) IsReady() bool {
	r := bool(C.wickra_realized_spread_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RealizedSpread) Name() string {
	r := C.GoString(C.wickra_realized_spread_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RealizedSpread) Update(price float64, size float64, isBuy bool, timestamp int64, mid float64) float64 {
	r := float64(C.wickra_realized_spread_update(ind.handle, C.double(price), C.double(size), C.bool(isBuy), C.int64_t(timestamp), C.double(mid)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RealizedSpread) Reset() {
	C.wickra_realized_spread_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RealizedSpread) Close() {
	if ind.handle != nil {
		C.wickra_realized_spread_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RealizedVolatility wraps the RealizedVolatility indicator over the Wickra C ABI.
type RealizedVolatility struct {
	handle *C.struct_RealizedVolatility
}

// NewRealizedVolatility constructs a RealizedVolatility. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRealizedVolatility(period int) (*RealizedVolatility, error) {
	ptr := C.wickra_realized_volatility_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RealizedVolatility{handle: ptr}
	runtime.SetFinalizer(obj, (*RealizedVolatility).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RealizedVolatility) WarmupPeriod() int {
	r := int(C.wickra_realized_volatility_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RealizedVolatility) IsReady() bool {
	r := bool(C.wickra_realized_volatility_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RealizedVolatility) Name() string {
	r := C.GoString(C.wickra_realized_volatility_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RealizedVolatility) Update(value float64) float64 {
	r := float64(C.wickra_realized_volatility_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *RealizedVolatility) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_realized_volatility_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RealizedVolatility) Reset() {
	C.wickra_realized_volatility_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RealizedVolatility) Close() {
	if ind.handle != nil {
		C.wickra_realized_volatility_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RecoveryFactor wraps the RecoveryFactor indicator over the Wickra C ABI.
type RecoveryFactor struct {
	handle *C.struct_RecoveryFactor
}

// NewRecoveryFactor constructs a RecoveryFactor. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRecoveryFactor() (*RecoveryFactor, error) {
	ptr := C.wickra_recovery_factor_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RecoveryFactor{handle: ptr}
	runtime.SetFinalizer(obj, (*RecoveryFactor).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RecoveryFactor) WarmupPeriod() int {
	r := int(C.wickra_recovery_factor_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RecoveryFactor) IsReady() bool {
	r := bool(C.wickra_recovery_factor_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RecoveryFactor) Name() string {
	r := C.GoString(C.wickra_recovery_factor_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RecoveryFactor) Update(value float64) float64 {
	r := float64(C.wickra_recovery_factor_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *RecoveryFactor) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_recovery_factor_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RecoveryFactor) Reset() {
	C.wickra_recovery_factor_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RecoveryFactor) Close() {
	if ind.handle != nil {
		C.wickra_recovery_factor_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RectangleRange wraps the RectangleRange indicator over the Wickra C ABI.
type RectangleRange struct {
	handle *C.struct_RectangleRange
}

// NewRectangleRange constructs a RectangleRange. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRectangleRange() (*RectangleRange, error) {
	ptr := C.wickra_rectangle_range_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RectangleRange{handle: ptr}
	runtime.SetFinalizer(obj, (*RectangleRange).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RectangleRange) WarmupPeriod() int {
	r := int(C.wickra_rectangle_range_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RectangleRange) IsReady() bool {
	r := bool(C.wickra_rectangle_range_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RectangleRange) Name() string {
	r := C.GoString(C.wickra_rectangle_range_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RectangleRange) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_rectangle_range_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *RectangleRange) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_rectangle_range_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RectangleRange) Reset() {
	C.wickra_rectangle_range_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RectangleRange) Close() {
	if ind.handle != nil {
		C.wickra_rectangle_range_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Reflex wraps the Reflex indicator over the Wickra C ABI.
type Reflex struct {
	handle *C.struct_Reflex
}

// NewReflex constructs a Reflex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewReflex(period int) (*Reflex, error) {
	ptr := C.wickra_reflex_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Reflex{handle: ptr}
	runtime.SetFinalizer(obj, (*Reflex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Reflex) WarmupPeriod() int {
	r := int(C.wickra_reflex_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Reflex) IsReady() bool {
	r := bool(C.wickra_reflex_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Reflex) Name() string {
	r := C.GoString(C.wickra_reflex_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Reflex) Update(value float64) float64 {
	r := float64(C.wickra_reflex_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Reflex) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_reflex_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Reflex) Reset() {
	C.wickra_reflex_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Reflex) Close() {
	if ind.handle != nil {
		C.wickra_reflex_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RegimeLabel wraps the RegimeLabel indicator over the Wickra C ABI.
type RegimeLabel struct {
	handle *C.struct_RegimeLabel
}

// NewRegimeLabel constructs a RegimeLabel. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRegimeLabel(volPeriod int, lookback int) (*RegimeLabel, error) {
	ptr := C.wickra_regime_label_new(C.uintptr_t(volPeriod), C.uintptr_t(lookback))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RegimeLabel{handle: ptr}
	runtime.SetFinalizer(obj, (*RegimeLabel).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RegimeLabel) WarmupPeriod() int {
	r := int(C.wickra_regime_label_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RegimeLabel) IsReady() bool {
	r := bool(C.wickra_regime_label_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RegimeLabel) Name() string {
	r := C.GoString(C.wickra_regime_label_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RegimeLabel) Update(value float64) float64 {
	r := float64(C.wickra_regime_label_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *RegimeLabel) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_regime_label_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RegimeLabel) Reset() {
	C.wickra_regime_label_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RegimeLabel) Close() {
	if ind.handle != nil {
		C.wickra_regime_label_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RelativeStrengthAB wraps the RelativeStrengthAB indicator over the Wickra C ABI.
type RelativeStrengthAB struct {
	handle *C.struct_RelativeStrengthAB
}

// NewRelativeStrengthAB constructs a RelativeStrengthAB. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRelativeStrengthAB(maPeriod int, rsiPeriod int) (*RelativeStrengthAB, error) {
	ptr := C.wickra_relative_strength_ab_new(C.uintptr_t(maPeriod), C.uintptr_t(rsiPeriod))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RelativeStrengthAB{handle: ptr}
	runtime.SetFinalizer(obj, (*RelativeStrengthAB).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RelativeStrengthAB) WarmupPeriod() int {
	r := int(C.wickra_relative_strength_ab_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RelativeStrengthAB) IsReady() bool {
	r := bool(C.wickra_relative_strength_ab_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RelativeStrengthAB) Name() string {
	r := C.GoString(C.wickra_relative_strength_ab_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *RelativeStrengthAB) Update(x float64, y float64) (RelativeStrengthOutput, bool) {
	var out C.struct_WickraRelativeStrengthOutput
	ok := bool(C.wickra_relative_strength_ab_update(ind.handle, C.double(x), C.double(y), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return RelativeStrengthOutput{}, false
	}
	return RelativeStrengthOutput{float64(out.ratio), float64(out.ratio_ma), float64(out.ratio_rsi)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RelativeStrengthAB) Reset() {
	C.wickra_relative_strength_ab_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RelativeStrengthAB) Close() {
	if ind.handle != nil {
		C.wickra_relative_strength_ab_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RenkoBars wraps the RenkoBars indicator over the Wickra C ABI.
type RenkoBars struct {
	handle *C.struct_RenkoBars
}

// NewRenkoBars constructs a RenkoBars. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRenkoBars(boxSize float64) (*RenkoBars, error) {
	ptr := C.wickra_renko_bars_new(C.double(boxSize))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RenkoBars{handle: ptr}
	runtime.SetFinalizer(obj, (*RenkoBars).Close)
	return obj, nil
}

// Name returns the indicator's canonical name.
func (ind *RenkoBars) Name() string {
	r := C.GoString(C.wickra_renko_bars_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one candle and returns any bars completed by it
// (a single candle may complete several).
func (ind *RenkoBars) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) []RenkoBrick {
	const capacity = 64
	var buf [capacity]C.struct_WickraRenkoBrick
	n := int(C.wickra_renko_bars_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &buf[0], C.uintptr_t(capacity)))
	runtime.KeepAlive(ind)
	if n <= 0 {
		return nil
	}
	out := make([]RenkoBrick, n)
	for i := 0; i < n; i++ {
		out[i] = RenkoBrick{float64(buf[i].open), float64(buf[i].close), int8(buf[i].direction)}
	}
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RenkoBars) Reset() {
	C.wickra_renko_bars_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RenkoBars) Close() {
	if ind.handle != nil {
		C.wickra_renko_bars_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RenkoTrailingStop wraps the RenkoTrailingStop indicator over the Wickra C ABI.
type RenkoTrailingStop struct {
	handle *C.struct_RenkoTrailingStop
}

// NewRenkoTrailingStop constructs a RenkoTrailingStop. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRenkoTrailingStop(blockSize float64) (*RenkoTrailingStop, error) {
	ptr := C.wickra_renko_trailing_stop_new(C.double(blockSize))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RenkoTrailingStop{handle: ptr}
	runtime.SetFinalizer(obj, (*RenkoTrailingStop).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RenkoTrailingStop) WarmupPeriod() int {
	r := int(C.wickra_renko_trailing_stop_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RenkoTrailingStop) IsReady() bool {
	r := bool(C.wickra_renko_trailing_stop_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RenkoTrailingStop) Name() string {
	r := C.GoString(C.wickra_renko_trailing_stop_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RenkoTrailingStop) Update(value float64) float64 {
	r := float64(C.wickra_renko_trailing_stop_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *RenkoTrailingStop) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_renko_trailing_stop_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RenkoTrailingStop) Reset() {
	C.wickra_renko_trailing_stop_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RenkoTrailingStop) Close() {
	if ind.handle != nil {
		C.wickra_renko_trailing_stop_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Resampler wraps the Resampler indicator over the Wickra C ABI.
type Resampler struct {
	handle *C.struct_Resampler
}

// NewResampler constructs a Resampler. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewResampler(timeframe int64) (*Resampler, error) {
	ptr := C.wickra_resampler_new(C.int64_t(timeframe))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Resampler{handle: ptr}
	runtime.SetFinalizer(obj, (*Resampler).Close)
	return obj, nil
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *Resampler) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (Candle, bool) {
	var out C.struct_WickraCandle
	ok := bool(C.wickra_resampler_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return Candle{}, false
	}
	return Candle{float64(out.open), float64(out.high), float64(out.low), float64(out.close), float64(out.volume), int64(out.timestamp)}, true
}

// Flush emits the final, still-open candle (ok is false if none is pending).
func (ind *Resampler) Flush() (Candle, bool) {
	var out C.struct_WickraCandle
	ok := bool(C.wickra_resampler_flush(ind.handle, &out))
	runtime.KeepAlive(ind)
	if !ok {
		return Candle{}, false
	}
	return Candle{float64(out.open), float64(out.high), float64(out.low), float64(out.close), float64(out.volume), int64(out.timestamp)}, true
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Resampler) Close() {
	if ind.handle != nil {
		C.wickra_resampler_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RickshawMan wraps the RickshawMan indicator over the Wickra C ABI.
type RickshawMan struct {
	handle *C.struct_RickshawMan
}

// NewRickshawMan constructs a RickshawMan. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRickshawMan() (*RickshawMan, error) {
	ptr := C.wickra_rickshaw_man_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RickshawMan{handle: ptr}
	runtime.SetFinalizer(obj, (*RickshawMan).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RickshawMan) WarmupPeriod() int {
	r := int(C.wickra_rickshaw_man_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RickshawMan) IsReady() bool {
	r := bool(C.wickra_rickshaw_man_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RickshawMan) Name() string {
	r := C.GoString(C.wickra_rickshaw_man_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RickshawMan) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_rickshaw_man_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *RickshawMan) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_rickshaw_man_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RickshawMan) Reset() {
	C.wickra_rickshaw_man_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RickshawMan) Close() {
	if ind.handle != nil {
		C.wickra_rickshaw_man_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RisingThreeMethods wraps the RisingThreeMethods indicator over the Wickra C ABI.
type RisingThreeMethods struct {
	handle *C.struct_RisingThreeMethods
}

// NewRisingThreeMethods constructs a RisingThreeMethods. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRisingThreeMethods() (*RisingThreeMethods, error) {
	ptr := C.wickra_rising_three_methods_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RisingThreeMethods{handle: ptr}
	runtime.SetFinalizer(obj, (*RisingThreeMethods).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RisingThreeMethods) WarmupPeriod() int {
	r := int(C.wickra_rising_three_methods_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RisingThreeMethods) IsReady() bool {
	r := bool(C.wickra_rising_three_methods_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RisingThreeMethods) Name() string {
	r := C.GoString(C.wickra_rising_three_methods_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RisingThreeMethods) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_rising_three_methods_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *RisingThreeMethods) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_rising_three_methods_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RisingThreeMethods) Reset() {
	C.wickra_rising_three_methods_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RisingThreeMethods) Close() {
	if ind.handle != nil {
		C.wickra_rising_three_methods_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Rmi wraps the Rmi indicator over the Wickra C ABI.
type Rmi struct {
	handle *C.struct_Rmi
}

// NewRmi constructs a Rmi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRmi(period int, momentum int) (*Rmi, error) {
	ptr := C.wickra_rmi_new(C.uintptr_t(period), C.uintptr_t(momentum))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Rmi{handle: ptr}
	runtime.SetFinalizer(obj, (*Rmi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Rmi) WarmupPeriod() int {
	r := int(C.wickra_rmi_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Rmi) IsReady() bool {
	r := bool(C.wickra_rmi_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Rmi) Name() string {
	r := C.GoString(C.wickra_rmi_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Rmi) Update(value float64) float64 {
	r := float64(C.wickra_rmi_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Rmi) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_rmi_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Rmi) Reset() {
	C.wickra_rmi_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Rmi) Close() {
	if ind.handle != nil {
		C.wickra_rmi_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Roc wraps the Roc indicator over the Wickra C ABI.
type Roc struct {
	handle *C.struct_Roc
}

// NewRoc constructs a Roc. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRoc(period int) (*Roc, error) {
	ptr := C.wickra_roc_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Roc{handle: ptr}
	runtime.SetFinalizer(obj, (*Roc).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Roc) WarmupPeriod() int {
	r := int(C.wickra_roc_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Roc) IsReady() bool {
	r := bool(C.wickra_roc_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Roc) Name() string {
	r := C.GoString(C.wickra_roc_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Roc) Update(value float64) float64 {
	r := float64(C.wickra_roc_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Roc) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_roc_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Roc) Reset() {
	C.wickra_roc_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Roc) Close() {
	if ind.handle != nil {
		C.wickra_roc_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Rocp wraps the Rocp indicator over the Wickra C ABI.
type Rocp struct {
	handle *C.struct_Rocp
}

// NewRocp constructs a Rocp. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRocp(period int) (*Rocp, error) {
	ptr := C.wickra_rocp_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Rocp{handle: ptr}
	runtime.SetFinalizer(obj, (*Rocp).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Rocp) WarmupPeriod() int {
	r := int(C.wickra_rocp_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Rocp) IsReady() bool {
	r := bool(C.wickra_rocp_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Rocp) Name() string {
	r := C.GoString(C.wickra_rocp_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Rocp) Update(value float64) float64 {
	r := float64(C.wickra_rocp_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Rocp) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_rocp_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Rocp) Reset() {
	C.wickra_rocp_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Rocp) Close() {
	if ind.handle != nil {
		C.wickra_rocp_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Rocr wraps the Rocr indicator over the Wickra C ABI.
type Rocr struct {
	handle *C.struct_Rocr
}

// NewRocr constructs a Rocr. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRocr(period int) (*Rocr, error) {
	ptr := C.wickra_rocr_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Rocr{handle: ptr}
	runtime.SetFinalizer(obj, (*Rocr).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Rocr) WarmupPeriod() int {
	r := int(C.wickra_rocr_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Rocr) IsReady() bool {
	r := bool(C.wickra_rocr_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Rocr) Name() string {
	r := C.GoString(C.wickra_rocr_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Rocr) Update(value float64) float64 {
	r := float64(C.wickra_rocr_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Rocr) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_rocr_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Rocr) Reset() {
	C.wickra_rocr_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Rocr) Close() {
	if ind.handle != nil {
		C.wickra_rocr_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Rocr100 wraps the Rocr100 indicator over the Wickra C ABI.
type Rocr100 struct {
	handle *C.struct_Rocr100
}

// NewRocr100 constructs a Rocr100. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRocr100(period int) (*Rocr100, error) {
	ptr := C.wickra_rocr100_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Rocr100{handle: ptr}
	runtime.SetFinalizer(obj, (*Rocr100).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Rocr100) WarmupPeriod() int {
	r := int(C.wickra_rocr100_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Rocr100) IsReady() bool {
	r := bool(C.wickra_rocr100_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Rocr100) Name() string {
	r := C.GoString(C.wickra_rocr100_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Rocr100) Update(value float64) float64 {
	r := float64(C.wickra_rocr100_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Rocr100) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_rocr100_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Rocr100) Reset() {
	C.wickra_rocr100_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Rocr100) Close() {
	if ind.handle != nil {
		C.wickra_rocr100_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RogersSatchellVolatility wraps the RogersSatchellVolatility indicator over the Wickra C ABI.
type RogersSatchellVolatility struct {
	handle *C.struct_RogersSatchellVolatility
}

// NewRogersSatchellVolatility constructs a RogersSatchellVolatility. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRogersSatchellVolatility(period int, tradingPeriods int) (*RogersSatchellVolatility, error) {
	ptr := C.wickra_rogers_satchell_volatility_new(C.uintptr_t(period), C.uintptr_t(tradingPeriods))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RogersSatchellVolatility{handle: ptr}
	runtime.SetFinalizer(obj, (*RogersSatchellVolatility).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RogersSatchellVolatility) WarmupPeriod() int {
	r := int(C.wickra_rogers_satchell_volatility_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RogersSatchellVolatility) IsReady() bool {
	r := bool(C.wickra_rogers_satchell_volatility_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RogersSatchellVolatility) Name() string {
	r := C.GoString(C.wickra_rogers_satchell_volatility_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RogersSatchellVolatility) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_rogers_satchell_volatility_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *RogersSatchellVolatility) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_rogers_satchell_volatility_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RogersSatchellVolatility) Reset() {
	C.wickra_rogers_satchell_volatility_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RogersSatchellVolatility) Close() {
	if ind.handle != nil {
		C.wickra_rogers_satchell_volatility_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RollMeasure wraps the RollMeasure indicator over the Wickra C ABI.
type RollMeasure struct {
	handle *C.struct_RollMeasure
}

// NewRollMeasure constructs a RollMeasure. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRollMeasure(period int) (*RollMeasure, error) {
	ptr := C.wickra_roll_measure_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RollMeasure{handle: ptr}
	runtime.SetFinalizer(obj, (*RollMeasure).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RollMeasure) WarmupPeriod() int {
	r := int(C.wickra_roll_measure_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RollMeasure) IsReady() bool {
	r := bool(C.wickra_roll_measure_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RollMeasure) Name() string {
	r := C.GoString(C.wickra_roll_measure_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RollMeasure) Update(price float64, size float64, isBuy bool, timestamp int64) float64 {
	r := float64(C.wickra_roll_measure_update(ind.handle, C.double(price), C.double(size), C.bool(isBuy), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RollMeasure) Reset() {
	C.wickra_roll_measure_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RollMeasure) Close() {
	if ind.handle != nil {
		C.wickra_roll_measure_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RollingCorrelation wraps the RollingCorrelation indicator over the Wickra C ABI.
type RollingCorrelation struct {
	handle *C.struct_RollingCorrelation
}

// NewRollingCorrelation constructs a RollingCorrelation. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRollingCorrelation(period int) (*RollingCorrelation, error) {
	ptr := C.wickra_rolling_correlation_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RollingCorrelation{handle: ptr}
	runtime.SetFinalizer(obj, (*RollingCorrelation).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RollingCorrelation) WarmupPeriod() int {
	r := int(C.wickra_rolling_correlation_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RollingCorrelation) IsReady() bool {
	r := bool(C.wickra_rolling_correlation_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RollingCorrelation) Name() string {
	r := C.GoString(C.wickra_rolling_correlation_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RollingCorrelation) Update(x float64, y float64) float64 {
	r := float64(C.wickra_rolling_correlation_update(ind.handle, C.double(x), C.double(y)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *RollingCorrelation) Batch(x []float64, y []float64) []float64 {
	n := len(x)
	if len(y) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_rolling_correlation_batch(ind.handle, (*C.double)(unsafe.Pointer(&x[0])), (*C.double)(unsafe.Pointer(&y[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(x)
	runtime.KeepAlive(y)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RollingCorrelation) Reset() {
	C.wickra_rolling_correlation_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RollingCorrelation) Close() {
	if ind.handle != nil {
		C.wickra_rolling_correlation_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RollingCovariance wraps the RollingCovariance indicator over the Wickra C ABI.
type RollingCovariance struct {
	handle *C.struct_RollingCovariance
}

// NewRollingCovariance constructs a RollingCovariance. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRollingCovariance(period int) (*RollingCovariance, error) {
	ptr := C.wickra_rolling_covariance_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RollingCovariance{handle: ptr}
	runtime.SetFinalizer(obj, (*RollingCovariance).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RollingCovariance) WarmupPeriod() int {
	r := int(C.wickra_rolling_covariance_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RollingCovariance) IsReady() bool {
	r := bool(C.wickra_rolling_covariance_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RollingCovariance) Name() string {
	r := C.GoString(C.wickra_rolling_covariance_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RollingCovariance) Update(x float64, y float64) float64 {
	r := float64(C.wickra_rolling_covariance_update(ind.handle, C.double(x), C.double(y)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *RollingCovariance) Batch(x []float64, y []float64) []float64 {
	n := len(x)
	if len(y) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_rolling_covariance_batch(ind.handle, (*C.double)(unsafe.Pointer(&x[0])), (*C.double)(unsafe.Pointer(&y[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(x)
	runtime.KeepAlive(y)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RollingCovariance) Reset() {
	C.wickra_rolling_covariance_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RollingCovariance) Close() {
	if ind.handle != nil {
		C.wickra_rolling_covariance_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RollingIqr wraps the RollingIqr indicator over the Wickra C ABI.
type RollingIqr struct {
	handle *C.struct_RollingIqr
}

// NewRollingIqr constructs a RollingIqr. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRollingIqr(period int) (*RollingIqr, error) {
	ptr := C.wickra_rolling_iqr_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RollingIqr{handle: ptr}
	runtime.SetFinalizer(obj, (*RollingIqr).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RollingIqr) WarmupPeriod() int {
	r := int(C.wickra_rolling_iqr_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RollingIqr) IsReady() bool {
	r := bool(C.wickra_rolling_iqr_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RollingIqr) Name() string {
	r := C.GoString(C.wickra_rolling_iqr_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RollingIqr) Update(value float64) float64 {
	r := float64(C.wickra_rolling_iqr_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *RollingIqr) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_rolling_iqr_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RollingIqr) Reset() {
	C.wickra_rolling_iqr_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RollingIqr) Close() {
	if ind.handle != nil {
		C.wickra_rolling_iqr_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RollingMinMaxScaler wraps the RollingMinMaxScaler indicator over the Wickra C ABI.
type RollingMinMaxScaler struct {
	handle *C.struct_RollingMinMaxScaler
}

// NewRollingMinMaxScaler constructs a RollingMinMaxScaler. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRollingMinMaxScaler(period int) (*RollingMinMaxScaler, error) {
	ptr := C.wickra_rolling_min_max_scaler_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RollingMinMaxScaler{handle: ptr}
	runtime.SetFinalizer(obj, (*RollingMinMaxScaler).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RollingMinMaxScaler) WarmupPeriod() int {
	r := int(C.wickra_rolling_min_max_scaler_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RollingMinMaxScaler) IsReady() bool {
	r := bool(C.wickra_rolling_min_max_scaler_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RollingMinMaxScaler) Name() string {
	r := C.GoString(C.wickra_rolling_min_max_scaler_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RollingMinMaxScaler) Update(value float64) float64 {
	r := float64(C.wickra_rolling_min_max_scaler_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *RollingMinMaxScaler) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_rolling_min_max_scaler_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RollingMinMaxScaler) Reset() {
	C.wickra_rolling_min_max_scaler_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RollingMinMaxScaler) Close() {
	if ind.handle != nil {
		C.wickra_rolling_min_max_scaler_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RollingPercentileRank wraps the RollingPercentileRank indicator over the Wickra C ABI.
type RollingPercentileRank struct {
	handle *C.struct_RollingPercentileRank
}

// NewRollingPercentileRank constructs a RollingPercentileRank. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRollingPercentileRank(period int) (*RollingPercentileRank, error) {
	ptr := C.wickra_rolling_percentile_rank_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RollingPercentileRank{handle: ptr}
	runtime.SetFinalizer(obj, (*RollingPercentileRank).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RollingPercentileRank) WarmupPeriod() int {
	r := int(C.wickra_rolling_percentile_rank_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RollingPercentileRank) IsReady() bool {
	r := bool(C.wickra_rolling_percentile_rank_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RollingPercentileRank) Name() string {
	r := C.GoString(C.wickra_rolling_percentile_rank_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RollingPercentileRank) Update(value float64) float64 {
	r := float64(C.wickra_rolling_percentile_rank_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *RollingPercentileRank) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_rolling_percentile_rank_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RollingPercentileRank) Reset() {
	C.wickra_rolling_percentile_rank_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RollingPercentileRank) Close() {
	if ind.handle != nil {
		C.wickra_rolling_percentile_rank_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RollingQuantile wraps the RollingQuantile indicator over the Wickra C ABI.
type RollingQuantile struct {
	handle *C.struct_RollingQuantile
}

// NewRollingQuantile constructs a RollingQuantile. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRollingQuantile(period int, quantile float64) (*RollingQuantile, error) {
	ptr := C.wickra_rolling_quantile_new(C.uintptr_t(period), C.double(quantile))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RollingQuantile{handle: ptr}
	runtime.SetFinalizer(obj, (*RollingQuantile).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RollingQuantile) WarmupPeriod() int {
	r := int(C.wickra_rolling_quantile_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RollingQuantile) IsReady() bool {
	r := bool(C.wickra_rolling_quantile_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RollingQuantile) Name() string {
	r := C.GoString(C.wickra_rolling_quantile_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RollingQuantile) Update(value float64) float64 {
	r := float64(C.wickra_rolling_quantile_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *RollingQuantile) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_rolling_quantile_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RollingQuantile) Reset() {
	C.wickra_rolling_quantile_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RollingQuantile) Close() {
	if ind.handle != nil {
		C.wickra_rolling_quantile_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RollingVwap wraps the RollingVwap indicator over the Wickra C ABI.
type RollingVwap struct {
	handle *C.struct_RollingVwap
}

// NewRollingVwap constructs a RollingVwap. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRollingVwap(period int) (*RollingVwap, error) {
	ptr := C.wickra_rolling_vwap_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RollingVwap{handle: ptr}
	runtime.SetFinalizer(obj, (*RollingVwap).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RollingVwap) WarmupPeriod() int {
	r := int(C.wickra_rolling_vwap_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RollingVwap) IsReady() bool {
	r := bool(C.wickra_rolling_vwap_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RollingVwap) Name() string {
	r := C.GoString(C.wickra_rolling_vwap_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RollingVwap) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_rolling_vwap_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *RollingVwap) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_rolling_vwap_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RollingVwap) Reset() {
	C.wickra_rolling_vwap_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RollingVwap) Close() {
	if ind.handle != nil {
		C.wickra_rolling_vwap_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RoofingFilter wraps the RoofingFilter indicator over the Wickra C ABI.
type RoofingFilter struct {
	handle *C.struct_RoofingFilter
}

// NewRoofingFilter constructs a RoofingFilter. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRoofingFilter(lpPeriod int, hpPeriod int) (*RoofingFilter, error) {
	ptr := C.wickra_roofing_filter_new(C.uintptr_t(lpPeriod), C.uintptr_t(hpPeriod))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RoofingFilter{handle: ptr}
	runtime.SetFinalizer(obj, (*RoofingFilter).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RoofingFilter) WarmupPeriod() int {
	r := int(C.wickra_roofing_filter_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RoofingFilter) IsReady() bool {
	r := bool(C.wickra_roofing_filter_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RoofingFilter) Name() string {
	r := C.GoString(C.wickra_roofing_filter_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RoofingFilter) Update(value float64) float64 {
	r := float64(C.wickra_roofing_filter_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *RoofingFilter) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_roofing_filter_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RoofingFilter) Reset() {
	C.wickra_roofing_filter_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RoofingFilter) Close() {
	if ind.handle != nil {
		C.wickra_roofing_filter_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Rsi wraps the Rsi indicator over the Wickra C ABI.
type Rsi struct {
	handle *C.struct_Rsi
}

// NewRsi constructs a Rsi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRsi(period int) (*Rsi, error) {
	ptr := C.wickra_rsi_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Rsi{handle: ptr}
	runtime.SetFinalizer(obj, (*Rsi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Rsi) WarmupPeriod() int {
	r := int(C.wickra_rsi_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Rsi) IsReady() bool {
	r := bool(C.wickra_rsi_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Rsi) Name() string {
	r := C.GoString(C.wickra_rsi_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Rsi) Update(value float64) float64 {
	r := float64(C.wickra_rsi_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Rsi) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_rsi_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Rsi) Reset() {
	C.wickra_rsi_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Rsi) Close() {
	if ind.handle != nil {
		C.wickra_rsi_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Rsx wraps the Rsx indicator over the Wickra C ABI.
type Rsx struct {
	handle *C.struct_Rsx
}

// NewRsx constructs a Rsx. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRsx(length int) (*Rsx, error) {
	ptr := C.wickra_rsx_new(C.uintptr_t(length))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Rsx{handle: ptr}
	runtime.SetFinalizer(obj, (*Rsx).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Rsx) WarmupPeriod() int {
	r := int(C.wickra_rsx_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Rsx) IsReady() bool {
	r := bool(C.wickra_rsx_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Rsx) Name() string {
	r := C.GoString(C.wickra_rsx_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Rsx) Update(value float64) float64 {
	r := float64(C.wickra_rsx_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Rsx) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_rsx_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Rsx) Reset() {
	C.wickra_rsx_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Rsx) Close() {
	if ind.handle != nil {
		C.wickra_rsx_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RunBars wraps the RunBars indicator over the Wickra C ABI.
type RunBars struct {
	handle *C.struct_RunBars
}

// NewRunBars constructs a RunBars. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRunBars(runLength int) (*RunBars, error) {
	ptr := C.wickra_run_bars_new(C.uintptr_t(runLength))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RunBars{handle: ptr}
	runtime.SetFinalizer(obj, (*RunBars).Close)
	return obj, nil
}

// Name returns the indicator's canonical name.
func (ind *RunBars) Name() string {
	r := C.GoString(C.wickra_run_bars_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one candle and returns any bars completed by it
// (a single candle may complete several).
func (ind *RunBars) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) []RunBar {
	const capacity = 64
	var buf [capacity]C.struct_WickraRunBar
	n := int(C.wickra_run_bars_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &buf[0], C.uintptr_t(capacity)))
	runtime.KeepAlive(ind)
	if n <= 0 {
		return nil
	}
	out := make([]RunBar, n)
	for i := 0; i < n; i++ {
		out[i] = RunBar{float64(buf[i].open), float64(buf[i].high), float64(buf[i].low), float64(buf[i].close), int(buf[i].length), int8(buf[i].direction)}
	}
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RunBars) Reset() {
	C.wickra_run_bars_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RunBars) Close() {
	if ind.handle != nil {
		C.wickra_run_bars_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Rvi wraps the Rvi indicator over the Wickra C ABI.
type Rvi struct {
	handle *C.struct_Rvi
}

// NewRvi constructs a Rvi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRvi(period int) (*Rvi, error) {
	ptr := C.wickra_rvi_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Rvi{handle: ptr}
	runtime.SetFinalizer(obj, (*Rvi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Rvi) WarmupPeriod() int {
	r := int(C.wickra_rvi_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Rvi) IsReady() bool {
	r := bool(C.wickra_rvi_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Rvi) Name() string {
	r := C.GoString(C.wickra_rvi_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Rvi) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_rvi_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Rvi) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_rvi_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Rvi) Reset() {
	C.wickra_rvi_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Rvi) Close() {
	if ind.handle != nil {
		C.wickra_rvi_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// RviVolatility wraps the RviVolatility indicator over the Wickra C ABI.
type RviVolatility struct {
	handle *C.struct_RviVolatility
}

// NewRviVolatility constructs a RviVolatility. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRviVolatility(period int) (*RviVolatility, error) {
	ptr := C.wickra_rvi_volatility_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &RviVolatility{handle: ptr}
	runtime.SetFinalizer(obj, (*RviVolatility).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *RviVolatility) WarmupPeriod() int {
	r := int(C.wickra_rvi_volatility_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *RviVolatility) IsReady() bool {
	r := bool(C.wickra_rvi_volatility_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *RviVolatility) Name() string {
	r := C.GoString(C.wickra_rvi_volatility_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *RviVolatility) Update(value float64) float64 {
	r := float64(C.wickra_rvi_volatility_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *RviVolatility) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_rvi_volatility_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *RviVolatility) Reset() {
	C.wickra_rvi_volatility_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *RviVolatility) Close() {
	if ind.handle != nil {
		C.wickra_rvi_volatility_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Rwi wraps the Rwi indicator over the Wickra C ABI.
type Rwi struct {
	handle *C.struct_Rwi
}

// NewRwi constructs a Rwi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewRwi(period int) (*Rwi, error) {
	ptr := C.wickra_rwi_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Rwi{handle: ptr}
	runtime.SetFinalizer(obj, (*Rwi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Rwi) WarmupPeriod() int {
	r := int(C.wickra_rwi_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Rwi) IsReady() bool {
	r := bool(C.wickra_rwi_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Rwi) Name() string {
	r := C.GoString(C.wickra_rwi_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *Rwi) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (RwiOutput, bool) {
	var out C.struct_WickraRwiOutput
	ok := bool(C.wickra_rwi_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return RwiOutput{}, false
	}
	return RwiOutput{float64(out.high), float64(out.low)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Rwi) Reset() {
	C.wickra_rwi_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Rwi) Close() {
	if ind.handle != nil {
		C.wickra_rwi_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SampleEntropy wraps the SampleEntropy indicator over the Wickra C ABI.
type SampleEntropy struct {
	handle *C.struct_SampleEntropy
}

// NewSampleEntropy constructs a SampleEntropy. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSampleEntropy(period int, m int, rFactor float64) (*SampleEntropy, error) {
	ptr := C.wickra_sample_entropy_new(C.uintptr_t(period), C.uintptr_t(m), C.double(rFactor))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SampleEntropy{handle: ptr}
	runtime.SetFinalizer(obj, (*SampleEntropy).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SampleEntropy) WarmupPeriod() int {
	r := int(C.wickra_sample_entropy_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SampleEntropy) IsReady() bool {
	r := bool(C.wickra_sample_entropy_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SampleEntropy) Name() string {
	r := C.GoString(C.wickra_sample_entropy_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *SampleEntropy) Update(value float64) float64 {
	r := float64(C.wickra_sample_entropy_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *SampleEntropy) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_sample_entropy_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SampleEntropy) Reset() {
	C.wickra_sample_entropy_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SampleEntropy) Close() {
	if ind.handle != nil {
		C.wickra_sample_entropy_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SarExt wraps the SarExt indicator over the Wickra C ABI.
type SarExt struct {
	handle *C.struct_SarExt
}

// NewSarExt constructs a SarExt. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSarExt(startValue float64, offsetOnReverse float64, accelInitLong float64, accelLong float64, accelMaxLong float64, accelInitShort float64, accelShort float64, accelMaxShort float64) (*SarExt, error) {
	ptr := C.wickra_sar_ext_new(C.double(startValue), C.double(offsetOnReverse), C.double(accelInitLong), C.double(accelLong), C.double(accelMaxLong), C.double(accelInitShort), C.double(accelShort), C.double(accelMaxShort))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SarExt{handle: ptr}
	runtime.SetFinalizer(obj, (*SarExt).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SarExt) WarmupPeriod() int {
	r := int(C.wickra_sar_ext_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SarExt) IsReady() bool {
	r := bool(C.wickra_sar_ext_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SarExt) Name() string {
	r := C.GoString(C.wickra_sar_ext_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *SarExt) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_sar_ext_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *SarExt) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_sar_ext_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SarExt) Reset() {
	C.wickra_sar_ext_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SarExt) Close() {
	if ind.handle != nil {
		C.wickra_sar_ext_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SeasonalZScore wraps the SeasonalZScore indicator over the Wickra C ABI.
type SeasonalZScore struct {
	handle *C.struct_SeasonalZScore
}

// NewSeasonalZScore constructs a SeasonalZScore. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSeasonalZScore(utcOffsetMinutes int32) (*SeasonalZScore, error) {
	ptr := C.wickra_seasonal_z_score_new(C.int32_t(utcOffsetMinutes))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SeasonalZScore{handle: ptr}
	runtime.SetFinalizer(obj, (*SeasonalZScore).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SeasonalZScore) WarmupPeriod() int {
	r := int(C.wickra_seasonal_z_score_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SeasonalZScore) IsReady() bool {
	r := bool(C.wickra_seasonal_z_score_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SeasonalZScore) Name() string {
	r := C.GoString(C.wickra_seasonal_z_score_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *SeasonalZScore) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_seasonal_z_score_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *SeasonalZScore) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_seasonal_z_score_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SeasonalZScore) Reset() {
	C.wickra_seasonal_z_score_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SeasonalZScore) Close() {
	if ind.handle != nil {
		C.wickra_seasonal_z_score_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SeparatingLines wraps the SeparatingLines indicator over the Wickra C ABI.
type SeparatingLines struct {
	handle *C.struct_SeparatingLines
}

// NewSeparatingLines constructs a SeparatingLines. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSeparatingLines() (*SeparatingLines, error) {
	ptr := C.wickra_separating_lines_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SeparatingLines{handle: ptr}
	runtime.SetFinalizer(obj, (*SeparatingLines).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SeparatingLines) WarmupPeriod() int {
	r := int(C.wickra_separating_lines_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SeparatingLines) IsReady() bool {
	r := bool(C.wickra_separating_lines_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SeparatingLines) Name() string {
	r := C.GoString(C.wickra_separating_lines_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *SeparatingLines) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_separating_lines_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *SeparatingLines) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_separating_lines_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SeparatingLines) Reset() {
	C.wickra_separating_lines_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SeparatingLines) Close() {
	if ind.handle != nil {
		C.wickra_separating_lines_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SessionHighLow wraps the SessionHighLow indicator over the Wickra C ABI.
type SessionHighLow struct {
	handle *C.struct_SessionHighLow
}

// NewSessionHighLow constructs a SessionHighLow. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSessionHighLow(utcOffsetMinutes int32) (*SessionHighLow, error) {
	ptr := C.wickra_session_high_low_new(C.int32_t(utcOffsetMinutes))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SessionHighLow{handle: ptr}
	runtime.SetFinalizer(obj, (*SessionHighLow).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SessionHighLow) WarmupPeriod() int {
	r := int(C.wickra_session_high_low_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SessionHighLow) IsReady() bool {
	r := bool(C.wickra_session_high_low_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SessionHighLow) Name() string {
	r := C.GoString(C.wickra_session_high_low_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *SessionHighLow) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (SessionHighLowOutput, bool) {
	var out C.struct_WickraSessionHighLowOutput
	ok := bool(C.wickra_session_high_low_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return SessionHighLowOutput{}, false
	}
	return SessionHighLowOutput{float64(out.high), float64(out.low)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SessionHighLow) Reset() {
	C.wickra_session_high_low_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SessionHighLow) Close() {
	if ind.handle != nil {
		C.wickra_session_high_low_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SessionRange wraps the SessionRange indicator over the Wickra C ABI.
type SessionRange struct {
	handle *C.struct_SessionRange
}

// NewSessionRange constructs a SessionRange. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSessionRange(utcOffsetMinutes int32) (*SessionRange, error) {
	ptr := C.wickra_session_range_new(C.int32_t(utcOffsetMinutes))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SessionRange{handle: ptr}
	runtime.SetFinalizer(obj, (*SessionRange).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SessionRange) WarmupPeriod() int {
	r := int(C.wickra_session_range_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SessionRange) IsReady() bool {
	r := bool(C.wickra_session_range_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SessionRange) Name() string {
	r := C.GoString(C.wickra_session_range_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *SessionRange) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (SessionRangeOutput, bool) {
	var out C.struct_WickraSessionRangeOutput
	ok := bool(C.wickra_session_range_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return SessionRangeOutput{}, false
	}
	return SessionRangeOutput{float64(out.asia), float64(out.eu), float64(out.us)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SessionRange) Reset() {
	C.wickra_session_range_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SessionRange) Close() {
	if ind.handle != nil {
		C.wickra_session_range_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SessionVwap wraps the SessionVwap indicator over the Wickra C ABI.
type SessionVwap struct {
	handle *C.struct_SessionVwap
}

// NewSessionVwap constructs a SessionVwap. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSessionVwap(utcOffsetMinutes int32) (*SessionVwap, error) {
	ptr := C.wickra_session_vwap_new(C.int32_t(utcOffsetMinutes))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SessionVwap{handle: ptr}
	runtime.SetFinalizer(obj, (*SessionVwap).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SessionVwap) WarmupPeriod() int {
	r := int(C.wickra_session_vwap_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SessionVwap) IsReady() bool {
	r := bool(C.wickra_session_vwap_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SessionVwap) Name() string {
	r := C.GoString(C.wickra_session_vwap_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *SessionVwap) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_session_vwap_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *SessionVwap) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_session_vwap_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SessionVwap) Reset() {
	C.wickra_session_vwap_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SessionVwap) Close() {
	if ind.handle != nil {
		C.wickra_session_vwap_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ShannonEntropy wraps the ShannonEntropy indicator over the Wickra C ABI.
type ShannonEntropy struct {
	handle *C.struct_ShannonEntropy
}

// NewShannonEntropy constructs a ShannonEntropy. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewShannonEntropy(period int, bins int) (*ShannonEntropy, error) {
	ptr := C.wickra_shannon_entropy_new(C.uintptr_t(period), C.uintptr_t(bins))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ShannonEntropy{handle: ptr}
	runtime.SetFinalizer(obj, (*ShannonEntropy).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ShannonEntropy) WarmupPeriod() int {
	r := int(C.wickra_shannon_entropy_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ShannonEntropy) IsReady() bool {
	r := bool(C.wickra_shannon_entropy_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ShannonEntropy) Name() string {
	r := C.GoString(C.wickra_shannon_entropy_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ShannonEntropy) Update(value float64) float64 {
	r := float64(C.wickra_shannon_entropy_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ShannonEntropy) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_shannon_entropy_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ShannonEntropy) Reset() {
	C.wickra_shannon_entropy_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ShannonEntropy) Close() {
	if ind.handle != nil {
		C.wickra_shannon_entropy_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Shark wraps the Shark indicator over the Wickra C ABI.
type Shark struct {
	handle *C.struct_Shark
}

// NewShark constructs a Shark. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewShark() (*Shark, error) {
	ptr := C.wickra_shark_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Shark{handle: ptr}
	runtime.SetFinalizer(obj, (*Shark).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Shark) WarmupPeriod() int {
	r := int(C.wickra_shark_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Shark) IsReady() bool {
	r := bool(C.wickra_shark_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Shark) Name() string {
	r := C.GoString(C.wickra_shark_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Shark) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_shark_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Shark) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_shark_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Shark) Reset() {
	C.wickra_shark_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Shark) Close() {
	if ind.handle != nil {
		C.wickra_shark_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SharpeRatio wraps the SharpeRatio indicator over the Wickra C ABI.
type SharpeRatio struct {
	handle *C.struct_SharpeRatio
}

// NewSharpeRatio constructs a SharpeRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSharpeRatio(period int, riskFree float64) (*SharpeRatio, error) {
	ptr := C.wickra_sharpe_ratio_new(C.uintptr_t(period), C.double(riskFree))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SharpeRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*SharpeRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SharpeRatio) WarmupPeriod() int {
	r := int(C.wickra_sharpe_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SharpeRatio) IsReady() bool {
	r := bool(C.wickra_sharpe_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SharpeRatio) Name() string {
	r := C.GoString(C.wickra_sharpe_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *SharpeRatio) Update(value float64) float64 {
	r := float64(C.wickra_sharpe_ratio_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *SharpeRatio) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_sharpe_ratio_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SharpeRatio) Reset() {
	C.wickra_sharpe_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SharpeRatio) Close() {
	if ind.handle != nil {
		C.wickra_sharpe_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ShootingStar wraps the ShootingStar indicator over the Wickra C ABI.
type ShootingStar struct {
	handle *C.struct_ShootingStar
}

// NewShootingStar constructs a ShootingStar. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewShootingStar() (*ShootingStar, error) {
	ptr := C.wickra_shooting_star_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ShootingStar{handle: ptr}
	runtime.SetFinalizer(obj, (*ShootingStar).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ShootingStar) WarmupPeriod() int {
	r := int(C.wickra_shooting_star_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ShootingStar) IsReady() bool {
	r := bool(C.wickra_shooting_star_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ShootingStar) Name() string {
	r := C.GoString(C.wickra_shooting_star_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ShootingStar) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_shooting_star_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ShootingStar) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_shooting_star_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ShootingStar) Reset() {
	C.wickra_shooting_star_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ShootingStar) Close() {
	if ind.handle != nil {
		C.wickra_shooting_star_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ShortLine wraps the ShortLine indicator over the Wickra C ABI.
type ShortLine struct {
	handle *C.struct_ShortLine
}

// NewShortLine constructs a ShortLine. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewShortLine() (*ShortLine, error) {
	ptr := C.wickra_short_line_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ShortLine{handle: ptr}
	runtime.SetFinalizer(obj, (*ShortLine).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ShortLine) WarmupPeriod() int {
	r := int(C.wickra_short_line_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ShortLine) IsReady() bool {
	r := bool(C.wickra_short_line_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ShortLine) Name() string {
	r := C.GoString(C.wickra_short_line_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ShortLine) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_short_line_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ShortLine) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_short_line_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ShortLine) Reset() {
	C.wickra_short_line_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ShortLine) Close() {
	if ind.handle != nil {
		C.wickra_short_line_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SignedVolume wraps the SignedVolume indicator over the Wickra C ABI.
type SignedVolume struct {
	handle *C.struct_SignedVolume
}

// NewSignedVolume constructs a SignedVolume. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSignedVolume() (*SignedVolume, error) {
	ptr := C.wickra_signed_volume_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SignedVolume{handle: ptr}
	runtime.SetFinalizer(obj, (*SignedVolume).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SignedVolume) WarmupPeriod() int {
	r := int(C.wickra_signed_volume_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SignedVolume) IsReady() bool {
	r := bool(C.wickra_signed_volume_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SignedVolume) Name() string {
	r := C.GoString(C.wickra_signed_volume_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *SignedVolume) Update(price float64, size float64, isBuy bool, timestamp int64) float64 {
	r := float64(C.wickra_signed_volume_update(ind.handle, C.double(price), C.double(size), C.bool(isBuy), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SignedVolume) Reset() {
	C.wickra_signed_volume_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SignedVolume) Close() {
	if ind.handle != nil {
		C.wickra_signed_volume_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SineWave wraps the SineWave indicator over the Wickra C ABI.
type SineWave struct {
	handle *C.struct_SineWave
}

// NewSineWave constructs a SineWave. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSineWave() (*SineWave, error) {
	ptr := C.wickra_sine_wave_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SineWave{handle: ptr}
	runtime.SetFinalizer(obj, (*SineWave).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SineWave) WarmupPeriod() int {
	r := int(C.wickra_sine_wave_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SineWave) IsReady() bool {
	r := bool(C.wickra_sine_wave_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SineWave) Name() string {
	r := C.GoString(C.wickra_sine_wave_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *SineWave) Update(value float64) float64 {
	r := float64(C.wickra_sine_wave_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *SineWave) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_sine_wave_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SineWave) Reset() {
	C.wickra_sine_wave_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SineWave) Close() {
	if ind.handle != nil {
		C.wickra_sine_wave_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SineWeightedMa wraps the SineWeightedMa indicator over the Wickra C ABI.
type SineWeightedMa struct {
	handle *C.struct_SineWeightedMa
}

// NewSineWeightedMa constructs a SineWeightedMa. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSineWeightedMa(period int) (*SineWeightedMa, error) {
	ptr := C.wickra_sine_weighted_ma_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SineWeightedMa{handle: ptr}
	runtime.SetFinalizer(obj, (*SineWeightedMa).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SineWeightedMa) WarmupPeriod() int {
	r := int(C.wickra_sine_weighted_ma_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SineWeightedMa) IsReady() bool {
	r := bool(C.wickra_sine_weighted_ma_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SineWeightedMa) Name() string {
	r := C.GoString(C.wickra_sine_weighted_ma_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *SineWeightedMa) Update(value float64) float64 {
	r := float64(C.wickra_sine_weighted_ma_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *SineWeightedMa) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_sine_weighted_ma_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SineWeightedMa) Reset() {
	C.wickra_sine_weighted_ma_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SineWeightedMa) Close() {
	if ind.handle != nil {
		C.wickra_sine_weighted_ma_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SinglePrints wraps the SinglePrints indicator over the Wickra C ABI.
type SinglePrints struct {
	handle *C.struct_SinglePrints
}

// NewSinglePrints constructs a SinglePrints. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSinglePrints(period int, bins int) (*SinglePrints, error) {
	ptr := C.wickra_single_prints_new(C.uintptr_t(period), C.uintptr_t(bins))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SinglePrints{handle: ptr}
	runtime.SetFinalizer(obj, (*SinglePrints).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SinglePrints) WarmupPeriod() int {
	r := int(C.wickra_single_prints_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SinglePrints) IsReady() bool {
	r := bool(C.wickra_single_prints_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SinglePrints) Name() string {
	r := C.GoString(C.wickra_single_prints_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *SinglePrints) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_single_prints_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *SinglePrints) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_single_prints_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SinglePrints) Reset() {
	C.wickra_single_prints_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SinglePrints) Close() {
	if ind.handle != nil {
		C.wickra_single_prints_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Skewness wraps the Skewness indicator over the Wickra C ABI.
type Skewness struct {
	handle *C.struct_Skewness
}

// NewSkewness constructs a Skewness. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSkewness(period int) (*Skewness, error) {
	ptr := C.wickra_skewness_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Skewness{handle: ptr}
	runtime.SetFinalizer(obj, (*Skewness).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Skewness) WarmupPeriod() int {
	r := int(C.wickra_skewness_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Skewness) IsReady() bool {
	r := bool(C.wickra_skewness_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Skewness) Name() string {
	r := C.GoString(C.wickra_skewness_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Skewness) Update(value float64) float64 {
	r := float64(C.wickra_skewness_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Skewness) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_skewness_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Skewness) Reset() {
	C.wickra_skewness_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Skewness) Close() {
	if ind.handle != nil {
		C.wickra_skewness_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Sma wraps the Sma indicator over the Wickra C ABI.
type Sma struct {
	handle *C.struct_Sma
}

// NewSma constructs a Sma. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSma(period int) (*Sma, error) {
	ptr := C.wickra_sma_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Sma{handle: ptr}
	runtime.SetFinalizer(obj, (*Sma).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Sma) WarmupPeriod() int {
	r := int(C.wickra_sma_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Sma) IsReady() bool {
	r := bool(C.wickra_sma_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Sma) Name() string {
	r := C.GoString(C.wickra_sma_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Sma) Update(value float64) float64 {
	r := float64(C.wickra_sma_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Sma) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_sma_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Sma) Reset() {
	C.wickra_sma_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Sma) Close() {
	if ind.handle != nil {
		C.wickra_sma_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Smi wraps the Smi indicator over the Wickra C ABI.
type Smi struct {
	handle *C.struct_Smi
}

// NewSmi constructs a Smi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSmi(period int, dPeriod int, d2Period int) (*Smi, error) {
	ptr := C.wickra_smi_new(C.uintptr_t(period), C.uintptr_t(dPeriod), C.uintptr_t(d2Period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Smi{handle: ptr}
	runtime.SetFinalizer(obj, (*Smi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Smi) WarmupPeriod() int {
	r := int(C.wickra_smi_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Smi) IsReady() bool {
	r := bool(C.wickra_smi_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Smi) Name() string {
	r := C.GoString(C.wickra_smi_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Smi) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_smi_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Smi) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_smi_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Smi) Reset() {
	C.wickra_smi_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Smi) Close() {
	if ind.handle != nil {
		C.wickra_smi_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Smma wraps the Smma indicator over the Wickra C ABI.
type Smma struct {
	handle *C.struct_Smma
}

// NewSmma constructs a Smma. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSmma(period int) (*Smma, error) {
	ptr := C.wickra_smma_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Smma{handle: ptr}
	runtime.SetFinalizer(obj, (*Smma).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Smma) WarmupPeriod() int {
	r := int(C.wickra_smma_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Smma) IsReady() bool {
	r := bool(C.wickra_smma_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Smma) Name() string {
	r := C.GoString(C.wickra_smma_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Smma) Update(value float64) float64 {
	r := float64(C.wickra_smma_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Smma) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_smma_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Smma) Reset() {
	C.wickra_smma_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Smma) Close() {
	if ind.handle != nil {
		C.wickra_smma_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SmoothedHeikinAshi wraps the SmoothedHeikinAshi indicator over the Wickra C ABI.
type SmoothedHeikinAshi struct {
	handle *C.struct_SmoothedHeikinAshi
}

// NewSmoothedHeikinAshi constructs a SmoothedHeikinAshi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSmoothedHeikinAshi(period int) (*SmoothedHeikinAshi, error) {
	ptr := C.wickra_smoothed_heikin_ashi_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SmoothedHeikinAshi{handle: ptr}
	runtime.SetFinalizer(obj, (*SmoothedHeikinAshi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SmoothedHeikinAshi) WarmupPeriod() int {
	r := int(C.wickra_smoothed_heikin_ashi_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SmoothedHeikinAshi) IsReady() bool {
	r := bool(C.wickra_smoothed_heikin_ashi_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SmoothedHeikinAshi) Name() string {
	r := C.GoString(C.wickra_smoothed_heikin_ashi_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *SmoothedHeikinAshi) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (SmoothedHeikinAshiOutput, bool) {
	var out C.struct_WickraSmoothedHeikinAshiOutput
	ok := bool(C.wickra_smoothed_heikin_ashi_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return SmoothedHeikinAshiOutput{}, false
	}
	return SmoothedHeikinAshiOutput{float64(out.open), float64(out.high), float64(out.low), float64(out.close)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SmoothedHeikinAshi) Reset() {
	C.wickra_smoothed_heikin_ashi_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SmoothedHeikinAshi) Close() {
	if ind.handle != nil {
		C.wickra_smoothed_heikin_ashi_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SortinoRatio wraps the SortinoRatio indicator over the Wickra C ABI.
type SortinoRatio struct {
	handle *C.struct_SortinoRatio
}

// NewSortinoRatio constructs a SortinoRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSortinoRatio(period int, mar float64) (*SortinoRatio, error) {
	ptr := C.wickra_sortino_ratio_new(C.uintptr_t(period), C.double(mar))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SortinoRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*SortinoRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SortinoRatio) WarmupPeriod() int {
	r := int(C.wickra_sortino_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SortinoRatio) IsReady() bool {
	r := bool(C.wickra_sortino_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SortinoRatio) Name() string {
	r := C.GoString(C.wickra_sortino_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *SortinoRatio) Update(value float64) float64 {
	r := float64(C.wickra_sortino_ratio_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *SortinoRatio) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_sortino_ratio_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SortinoRatio) Reset() {
	C.wickra_sortino_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SortinoRatio) Close() {
	if ind.handle != nil {
		C.wickra_sortino_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SpearmanCorrelation wraps the SpearmanCorrelation indicator over the Wickra C ABI.
type SpearmanCorrelation struct {
	handle *C.struct_SpearmanCorrelation
}

// NewSpearmanCorrelation constructs a SpearmanCorrelation. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSpearmanCorrelation(period int) (*SpearmanCorrelation, error) {
	ptr := C.wickra_spearman_correlation_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SpearmanCorrelation{handle: ptr}
	runtime.SetFinalizer(obj, (*SpearmanCorrelation).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SpearmanCorrelation) WarmupPeriod() int {
	r := int(C.wickra_spearman_correlation_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SpearmanCorrelation) IsReady() bool {
	r := bool(C.wickra_spearman_correlation_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SpearmanCorrelation) Name() string {
	r := C.GoString(C.wickra_spearman_correlation_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *SpearmanCorrelation) Update(x float64, y float64) float64 {
	r := float64(C.wickra_spearman_correlation_update(ind.handle, C.double(x), C.double(y)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *SpearmanCorrelation) Batch(x []float64, y []float64) []float64 {
	n := len(x)
	if len(y) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_spearman_correlation_batch(ind.handle, (*C.double)(unsafe.Pointer(&x[0])), (*C.double)(unsafe.Pointer(&y[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(x)
	runtime.KeepAlive(y)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SpearmanCorrelation) Reset() {
	C.wickra_spearman_correlation_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SpearmanCorrelation) Close() {
	if ind.handle != nil {
		C.wickra_spearman_correlation_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SpinningTop wraps the SpinningTop indicator over the Wickra C ABI.
type SpinningTop struct {
	handle *C.struct_SpinningTop
}

// NewSpinningTop constructs a SpinningTop. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSpinningTop() (*SpinningTop, error) {
	ptr := C.wickra_spinning_top_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SpinningTop{handle: ptr}
	runtime.SetFinalizer(obj, (*SpinningTop).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SpinningTop) WarmupPeriod() int {
	r := int(C.wickra_spinning_top_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SpinningTop) IsReady() bool {
	r := bool(C.wickra_spinning_top_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SpinningTop) Name() string {
	r := C.GoString(C.wickra_spinning_top_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *SpinningTop) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_spinning_top_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *SpinningTop) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_spinning_top_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SpinningTop) Reset() {
	C.wickra_spinning_top_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SpinningTop) Close() {
	if ind.handle != nil {
		C.wickra_spinning_top_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SpreadAr1Coefficient wraps the SpreadAr1Coefficient indicator over the Wickra C ABI.
type SpreadAr1Coefficient struct {
	handle *C.struct_SpreadAr1Coefficient
}

// NewSpreadAr1Coefficient constructs a SpreadAr1Coefficient. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSpreadAr1Coefficient(period int) (*SpreadAr1Coefficient, error) {
	ptr := C.wickra_spread_ar1_coefficient_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SpreadAr1Coefficient{handle: ptr}
	runtime.SetFinalizer(obj, (*SpreadAr1Coefficient).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SpreadAr1Coefficient) WarmupPeriod() int {
	r := int(C.wickra_spread_ar1_coefficient_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SpreadAr1Coefficient) IsReady() bool {
	r := bool(C.wickra_spread_ar1_coefficient_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SpreadAr1Coefficient) Name() string {
	r := C.GoString(C.wickra_spread_ar1_coefficient_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *SpreadAr1Coefficient) Update(x float64, y float64) float64 {
	r := float64(C.wickra_spread_ar1_coefficient_update(ind.handle, C.double(x), C.double(y)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *SpreadAr1Coefficient) Batch(x []float64, y []float64) []float64 {
	n := len(x)
	if len(y) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_spread_ar1_coefficient_batch(ind.handle, (*C.double)(unsafe.Pointer(&x[0])), (*C.double)(unsafe.Pointer(&y[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(x)
	runtime.KeepAlive(y)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SpreadAr1Coefficient) Reset() {
	C.wickra_spread_ar1_coefficient_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SpreadAr1Coefficient) Close() {
	if ind.handle != nil {
		C.wickra_spread_ar1_coefficient_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SpreadBollingerBands wraps the SpreadBollingerBands indicator over the Wickra C ABI.
type SpreadBollingerBands struct {
	handle *C.struct_SpreadBollingerBands
}

// NewSpreadBollingerBands constructs a SpreadBollingerBands. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSpreadBollingerBands(period int, numStd float64) (*SpreadBollingerBands, error) {
	ptr := C.wickra_spread_bollinger_bands_new(C.uintptr_t(period), C.double(numStd))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SpreadBollingerBands{handle: ptr}
	runtime.SetFinalizer(obj, (*SpreadBollingerBands).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SpreadBollingerBands) WarmupPeriod() int {
	r := int(C.wickra_spread_bollinger_bands_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SpreadBollingerBands) IsReady() bool {
	r := bool(C.wickra_spread_bollinger_bands_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SpreadBollingerBands) Name() string {
	r := C.GoString(C.wickra_spread_bollinger_bands_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *SpreadBollingerBands) Update(x float64, y float64) (SpreadBollingerBandsOutput, bool) {
	var out C.struct_WickraSpreadBollingerBandsOutput
	ok := bool(C.wickra_spread_bollinger_bands_update(ind.handle, C.double(x), C.double(y), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return SpreadBollingerBandsOutput{}, false
	}
	return SpreadBollingerBandsOutput{float64(out.middle), float64(out.upper), float64(out.lower), float64(out.percent_b)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SpreadBollingerBands) Reset() {
	C.wickra_spread_bollinger_bands_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SpreadBollingerBands) Close() {
	if ind.handle != nil {
		C.wickra_spread_bollinger_bands_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SpreadHurst wraps the SpreadHurst indicator over the Wickra C ABI.
type SpreadHurst struct {
	handle *C.struct_SpreadHurst
}

// NewSpreadHurst constructs a SpreadHurst. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSpreadHurst(period int) (*SpreadHurst, error) {
	ptr := C.wickra_spread_hurst_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SpreadHurst{handle: ptr}
	runtime.SetFinalizer(obj, (*SpreadHurst).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SpreadHurst) WarmupPeriod() int {
	r := int(C.wickra_spread_hurst_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SpreadHurst) IsReady() bool {
	r := bool(C.wickra_spread_hurst_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SpreadHurst) Name() string {
	r := C.GoString(C.wickra_spread_hurst_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *SpreadHurst) Update(x float64, y float64) float64 {
	r := float64(C.wickra_spread_hurst_update(ind.handle, C.double(x), C.double(y)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *SpreadHurst) Batch(x []float64, y []float64) []float64 {
	n := len(x)
	if len(y) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_spread_hurst_batch(ind.handle, (*C.double)(unsafe.Pointer(&x[0])), (*C.double)(unsafe.Pointer(&y[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(x)
	runtime.KeepAlive(y)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SpreadHurst) Reset() {
	C.wickra_spread_hurst_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SpreadHurst) Close() {
	if ind.handle != nil {
		C.wickra_spread_hurst_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// StalledPattern wraps the StalledPattern indicator over the Wickra C ABI.
type StalledPattern struct {
	handle *C.struct_StalledPattern
}

// NewStalledPattern constructs a StalledPattern. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewStalledPattern() (*StalledPattern, error) {
	ptr := C.wickra_stalled_pattern_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &StalledPattern{handle: ptr}
	runtime.SetFinalizer(obj, (*StalledPattern).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *StalledPattern) WarmupPeriod() int {
	r := int(C.wickra_stalled_pattern_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *StalledPattern) IsReady() bool {
	r := bool(C.wickra_stalled_pattern_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *StalledPattern) Name() string {
	r := C.GoString(C.wickra_stalled_pattern_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *StalledPattern) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_stalled_pattern_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *StalledPattern) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_stalled_pattern_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *StalledPattern) Reset() {
	C.wickra_stalled_pattern_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *StalledPattern) Close() {
	if ind.handle != nil {
		C.wickra_stalled_pattern_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// StandardError wraps the StandardError indicator over the Wickra C ABI.
type StandardError struct {
	handle *C.struct_StandardError
}

// NewStandardError constructs a StandardError. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewStandardError(period int) (*StandardError, error) {
	ptr := C.wickra_standard_error_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &StandardError{handle: ptr}
	runtime.SetFinalizer(obj, (*StandardError).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *StandardError) WarmupPeriod() int {
	r := int(C.wickra_standard_error_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *StandardError) IsReady() bool {
	r := bool(C.wickra_standard_error_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *StandardError) Name() string {
	r := C.GoString(C.wickra_standard_error_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *StandardError) Update(value float64) float64 {
	r := float64(C.wickra_standard_error_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *StandardError) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_standard_error_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *StandardError) Reset() {
	C.wickra_standard_error_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *StandardError) Close() {
	if ind.handle != nil {
		C.wickra_standard_error_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// StandardErrorBands wraps the StandardErrorBands indicator over the Wickra C ABI.
type StandardErrorBands struct {
	handle *C.struct_StandardErrorBands
}

// NewStandardErrorBands constructs a StandardErrorBands. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewStandardErrorBands(period int, multiplier float64) (*StandardErrorBands, error) {
	ptr := C.wickra_standard_error_bands_new(C.uintptr_t(period), C.double(multiplier))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &StandardErrorBands{handle: ptr}
	runtime.SetFinalizer(obj, (*StandardErrorBands).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *StandardErrorBands) WarmupPeriod() int {
	r := int(C.wickra_standard_error_bands_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *StandardErrorBands) IsReady() bool {
	r := bool(C.wickra_standard_error_bands_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *StandardErrorBands) Name() string {
	r := C.GoString(C.wickra_standard_error_bands_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *StandardErrorBands) Update(value float64) (StandardErrorBandsOutput, bool) {
	var out C.struct_WickraStandardErrorBandsOutput
	ok := bool(C.wickra_standard_error_bands_update(ind.handle, C.double(value), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return StandardErrorBandsOutput{}, false
	}
	return StandardErrorBandsOutput{float64(out.upper), float64(out.middle), float64(out.lower)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *StandardErrorBands) Reset() {
	C.wickra_standard_error_bands_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *StandardErrorBands) Close() {
	if ind.handle != nil {
		C.wickra_standard_error_bands_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// StarcBands wraps the StarcBands indicator over the Wickra C ABI.
type StarcBands struct {
	handle *C.struct_StarcBands
}

// NewStarcBands constructs a StarcBands. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewStarcBands(smaPeriod int, atrPeriod int, multiplier float64) (*StarcBands, error) {
	ptr := C.wickra_starc_bands_new(C.uintptr_t(smaPeriod), C.uintptr_t(atrPeriod), C.double(multiplier))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &StarcBands{handle: ptr}
	runtime.SetFinalizer(obj, (*StarcBands).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *StarcBands) WarmupPeriod() int {
	r := int(C.wickra_starc_bands_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *StarcBands) IsReady() bool {
	r := bool(C.wickra_starc_bands_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *StarcBands) Name() string {
	r := C.GoString(C.wickra_starc_bands_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *StarcBands) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (StarcBandsOutput, bool) {
	var out C.struct_WickraStarcBandsOutput
	ok := bool(C.wickra_starc_bands_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return StarcBandsOutput{}, false
	}
	return StarcBandsOutput{float64(out.upper), float64(out.middle), float64(out.lower)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *StarcBands) Reset() {
	C.wickra_starc_bands_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *StarcBands) Close() {
	if ind.handle != nil {
		C.wickra_starc_bands_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Stc wraps the Stc indicator over the Wickra C ABI.
type Stc struct {
	handle *C.struct_Stc
}

// NewStc constructs a Stc. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewStc(fast int, slow int, schaffPeriod int, factor float64) (*Stc, error) {
	ptr := C.wickra_stc_new(C.uintptr_t(fast), C.uintptr_t(slow), C.uintptr_t(schaffPeriod), C.double(factor))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Stc{handle: ptr}
	runtime.SetFinalizer(obj, (*Stc).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Stc) WarmupPeriod() int {
	r := int(C.wickra_stc_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Stc) IsReady() bool {
	r := bool(C.wickra_stc_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Stc) Name() string {
	r := C.GoString(C.wickra_stc_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Stc) Update(value float64) float64 {
	r := float64(C.wickra_stc_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Stc) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_stc_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Stc) Reset() {
	C.wickra_stc_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Stc) Close() {
	if ind.handle != nil {
		C.wickra_stc_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// StdDev wraps the StdDev indicator over the Wickra C ABI.
type StdDev struct {
	handle *C.struct_StdDev
}

// NewStdDev constructs a StdDev. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewStdDev(period int) (*StdDev, error) {
	ptr := C.wickra_std_dev_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &StdDev{handle: ptr}
	runtime.SetFinalizer(obj, (*StdDev).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *StdDev) WarmupPeriod() int {
	r := int(C.wickra_std_dev_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *StdDev) IsReady() bool {
	r := bool(C.wickra_std_dev_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *StdDev) Name() string {
	r := C.GoString(C.wickra_std_dev_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *StdDev) Update(value float64) float64 {
	r := float64(C.wickra_std_dev_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *StdDev) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_std_dev_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *StdDev) Reset() {
	C.wickra_std_dev_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *StdDev) Close() {
	if ind.handle != nil {
		C.wickra_std_dev_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// StepTrailingStop wraps the StepTrailingStop indicator over the Wickra C ABI.
type StepTrailingStop struct {
	handle *C.struct_StepTrailingStop
}

// NewStepTrailingStop constructs a StepTrailingStop. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewStepTrailingStop(stepSize float64) (*StepTrailingStop, error) {
	ptr := C.wickra_step_trailing_stop_new(C.double(stepSize))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &StepTrailingStop{handle: ptr}
	runtime.SetFinalizer(obj, (*StepTrailingStop).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *StepTrailingStop) WarmupPeriod() int {
	r := int(C.wickra_step_trailing_stop_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *StepTrailingStop) IsReady() bool {
	r := bool(C.wickra_step_trailing_stop_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *StepTrailingStop) Name() string {
	r := C.GoString(C.wickra_step_trailing_stop_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *StepTrailingStop) Update(value float64) float64 {
	r := float64(C.wickra_step_trailing_stop_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *StepTrailingStop) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_step_trailing_stop_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *StepTrailingStop) Reset() {
	C.wickra_step_trailing_stop_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *StepTrailingStop) Close() {
	if ind.handle != nil {
		C.wickra_step_trailing_stop_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SterlingRatio wraps the SterlingRatio indicator over the Wickra C ABI.
type SterlingRatio struct {
	handle *C.struct_SterlingRatio
}

// NewSterlingRatio constructs a SterlingRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSterlingRatio(period int) (*SterlingRatio, error) {
	ptr := C.wickra_sterling_ratio_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SterlingRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*SterlingRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SterlingRatio) WarmupPeriod() int {
	r := int(C.wickra_sterling_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SterlingRatio) IsReady() bool {
	r := bool(C.wickra_sterling_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SterlingRatio) Name() string {
	r := C.GoString(C.wickra_sterling_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *SterlingRatio) Update(value float64) float64 {
	r := float64(C.wickra_sterling_ratio_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *SterlingRatio) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_sterling_ratio_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SterlingRatio) Reset() {
	C.wickra_sterling_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SterlingRatio) Close() {
	if ind.handle != nil {
		C.wickra_sterling_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// StickSandwich wraps the StickSandwich indicator over the Wickra C ABI.
type StickSandwich struct {
	handle *C.struct_StickSandwich
}

// NewStickSandwich constructs a StickSandwich. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewStickSandwich() (*StickSandwich, error) {
	ptr := C.wickra_stick_sandwich_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &StickSandwich{handle: ptr}
	runtime.SetFinalizer(obj, (*StickSandwich).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *StickSandwich) WarmupPeriod() int {
	r := int(C.wickra_stick_sandwich_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *StickSandwich) IsReady() bool {
	r := bool(C.wickra_stick_sandwich_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *StickSandwich) Name() string {
	r := C.GoString(C.wickra_stick_sandwich_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *StickSandwich) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_stick_sandwich_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *StickSandwich) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_stick_sandwich_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *StickSandwich) Reset() {
	C.wickra_stick_sandwich_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *StickSandwich) Close() {
	if ind.handle != nil {
		C.wickra_stick_sandwich_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// StochRsi wraps the StochRsi indicator over the Wickra C ABI.
type StochRsi struct {
	handle *C.struct_StochRsi
}

// NewStochRsi constructs a StochRsi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewStochRsi(rsiPeriod int, stochPeriod int) (*StochRsi, error) {
	ptr := C.wickra_stoch_rsi_new(C.uintptr_t(rsiPeriod), C.uintptr_t(stochPeriod))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &StochRsi{handle: ptr}
	runtime.SetFinalizer(obj, (*StochRsi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *StochRsi) WarmupPeriod() int {
	r := int(C.wickra_stoch_rsi_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *StochRsi) IsReady() bool {
	r := bool(C.wickra_stoch_rsi_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *StochRsi) Name() string {
	r := C.GoString(C.wickra_stoch_rsi_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *StochRsi) Update(value float64) float64 {
	r := float64(C.wickra_stoch_rsi_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *StochRsi) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_stoch_rsi_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *StochRsi) Reset() {
	C.wickra_stoch_rsi_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *StochRsi) Close() {
	if ind.handle != nil {
		C.wickra_stoch_rsi_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Stochastic wraps the Stochastic indicator over the Wickra C ABI.
type Stochastic struct {
	handle *C.struct_Stochastic
}

// NewStochastic constructs a Stochastic. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewStochastic(kPeriod int, dPeriod int) (*Stochastic, error) {
	ptr := C.wickra_stochastic_new(C.uintptr_t(kPeriod), C.uintptr_t(dPeriod))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Stochastic{handle: ptr}
	runtime.SetFinalizer(obj, (*Stochastic).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Stochastic) WarmupPeriod() int {
	r := int(C.wickra_stochastic_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Stochastic) IsReady() bool {
	r := bool(C.wickra_stochastic_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Stochastic) Name() string {
	r := C.GoString(C.wickra_stochastic_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *Stochastic) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (StochasticOutput, bool) {
	var out C.struct_WickraStochasticOutput
	ok := bool(C.wickra_stochastic_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return StochasticOutput{}, false
	}
	return StochasticOutput{float64(out.k), float64(out.d)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Stochastic) Reset() {
	C.wickra_stochastic_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Stochastic) Close() {
	if ind.handle != nil {
		C.wickra_stochastic_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// StochasticCci wraps the StochasticCci indicator over the Wickra C ABI.
type StochasticCci struct {
	handle *C.struct_StochasticCci
}

// NewStochasticCci constructs a StochasticCci. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewStochasticCci(period int) (*StochasticCci, error) {
	ptr := C.wickra_stochastic_cci_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &StochasticCci{handle: ptr}
	runtime.SetFinalizer(obj, (*StochasticCci).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *StochasticCci) WarmupPeriod() int {
	r := int(C.wickra_stochastic_cci_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *StochasticCci) IsReady() bool {
	r := bool(C.wickra_stochastic_cci_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *StochasticCci) Name() string {
	r := C.GoString(C.wickra_stochastic_cci_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *StochasticCci) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_stochastic_cci_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *StochasticCci) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_stochastic_cci_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *StochasticCci) Reset() {
	C.wickra_stochastic_cci_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *StochasticCci) Close() {
	if ind.handle != nil {
		C.wickra_stochastic_cci_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SuperSmoother wraps the SuperSmoother indicator over the Wickra C ABI.
type SuperSmoother struct {
	handle *C.struct_SuperSmoother
}

// NewSuperSmoother constructs a SuperSmoother. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSuperSmoother(period int) (*SuperSmoother, error) {
	ptr := C.wickra_super_smoother_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SuperSmoother{handle: ptr}
	runtime.SetFinalizer(obj, (*SuperSmoother).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SuperSmoother) WarmupPeriod() int {
	r := int(C.wickra_super_smoother_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SuperSmoother) IsReady() bool {
	r := bool(C.wickra_super_smoother_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SuperSmoother) Name() string {
	r := C.GoString(C.wickra_super_smoother_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *SuperSmoother) Update(value float64) float64 {
	r := float64(C.wickra_super_smoother_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *SuperSmoother) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_super_smoother_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SuperSmoother) Reset() {
	C.wickra_super_smoother_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SuperSmoother) Close() {
	if ind.handle != nil {
		C.wickra_super_smoother_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// SuperTrend wraps the SuperTrend indicator over the Wickra C ABI.
type SuperTrend struct {
	handle *C.struct_SuperTrend
}

// NewSuperTrend constructs a SuperTrend. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewSuperTrend(atrPeriod int, multiplier float64) (*SuperTrend, error) {
	ptr := C.wickra_super_trend_new(C.uintptr_t(atrPeriod), C.double(multiplier))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &SuperTrend{handle: ptr}
	runtime.SetFinalizer(obj, (*SuperTrend).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *SuperTrend) WarmupPeriod() int {
	r := int(C.wickra_super_trend_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *SuperTrend) IsReady() bool {
	r := bool(C.wickra_super_trend_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *SuperTrend) Name() string {
	r := C.GoString(C.wickra_super_trend_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *SuperTrend) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (SuperTrendOutput, bool) {
	var out C.struct_WickraSuperTrendOutput
	ok := bool(C.wickra_super_trend_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return SuperTrendOutput{}, false
	}
	return SuperTrendOutput{float64(out.value), float64(out.direction)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *SuperTrend) Reset() {
	C.wickra_super_trend_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *SuperTrend) Close() {
	if ind.handle != nil {
		C.wickra_super_trend_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// T3 wraps the T3 indicator over the Wickra C ABI.
type T3 struct {
	handle *C.struct_T3
}

// NewT3 constructs a T3. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewT3(period int, v float64) (*T3, error) {
	ptr := C.wickra_t3_new(C.uintptr_t(period), C.double(v))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &T3{handle: ptr}
	runtime.SetFinalizer(obj, (*T3).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *T3) WarmupPeriod() int {
	r := int(C.wickra_t3_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *T3) IsReady() bool {
	r := bool(C.wickra_t3_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *T3) Name() string {
	r := C.GoString(C.wickra_t3_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *T3) Update(value float64) float64 {
	r := float64(C.wickra_t3_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *T3) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_t3_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *T3) Reset() {
	C.wickra_t3_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *T3) Close() {
	if ind.handle != nil {
		C.wickra_t3_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TailRatio wraps the TailRatio indicator over the Wickra C ABI.
type TailRatio struct {
	handle *C.struct_TailRatio
}

// NewTailRatio constructs a TailRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTailRatio(period int) (*TailRatio, error) {
	ptr := C.wickra_tail_ratio_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TailRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*TailRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TailRatio) WarmupPeriod() int {
	r := int(C.wickra_tail_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TailRatio) IsReady() bool {
	r := bool(C.wickra_tail_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TailRatio) Name() string {
	r := C.GoString(C.wickra_tail_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TailRatio) Update(value float64) float64 {
	r := float64(C.wickra_tail_ratio_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TailRatio) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_tail_ratio_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TailRatio) Reset() {
	C.wickra_tail_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TailRatio) Close() {
	if ind.handle != nil {
		C.wickra_tail_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TakerBuySellRatio wraps the TakerBuySellRatio indicator over the Wickra C ABI.
type TakerBuySellRatio struct {
	handle *C.struct_TakerBuySellRatio
}

// NewTakerBuySellRatio constructs a TakerBuySellRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTakerBuySellRatio() (*TakerBuySellRatio, error) {
	ptr := C.wickra_taker_buy_sell_ratio_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TakerBuySellRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*TakerBuySellRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TakerBuySellRatio) WarmupPeriod() int {
	r := int(C.wickra_taker_buy_sell_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TakerBuySellRatio) IsReady() bool {
	r := bool(C.wickra_taker_buy_sell_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TakerBuySellRatio) Name() string {
	r := C.GoString(C.wickra_taker_buy_sell_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TakerBuySellRatio) Update(fundingRate float64, markPrice float64, indexPrice float64, futuresPrice float64, openInterest float64, longSize float64, shortSize float64, takerBuyVolume float64, takerSellVolume float64, longLiquidation float64, shortLiquidation float64, timestamp int64) float64 {
	r := float64(C.wickra_taker_buy_sell_ratio_update(ind.handle, C.double(fundingRate), C.double(markPrice), C.double(indexPrice), C.double(futuresPrice), C.double(openInterest), C.double(longSize), C.double(shortSize), C.double(takerBuyVolume), C.double(takerSellVolume), C.double(longLiquidation), C.double(shortLiquidation), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TakerBuySellRatio) Reset() {
	C.wickra_taker_buy_sell_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TakerBuySellRatio) Close() {
	if ind.handle != nil {
		C.wickra_taker_buy_sell_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Takuri wraps the Takuri indicator over the Wickra C ABI.
type Takuri struct {
	handle *C.struct_Takuri
}

// NewTakuri constructs a Takuri. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTakuri() (*Takuri, error) {
	ptr := C.wickra_takuri_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Takuri{handle: ptr}
	runtime.SetFinalizer(obj, (*Takuri).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Takuri) WarmupPeriod() int {
	r := int(C.wickra_takuri_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Takuri) IsReady() bool {
	r := bool(C.wickra_takuri_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Takuri) Name() string {
	r := C.GoString(C.wickra_takuri_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Takuri) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_takuri_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Takuri) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_takuri_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Takuri) Reset() {
	C.wickra_takuri_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Takuri) Close() {
	if ind.handle != nil {
		C.wickra_takuri_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TasukiGap wraps the TasukiGap indicator over the Wickra C ABI.
type TasukiGap struct {
	handle *C.struct_TasukiGap
}

// NewTasukiGap constructs a TasukiGap. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTasukiGap() (*TasukiGap, error) {
	ptr := C.wickra_tasuki_gap_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TasukiGap{handle: ptr}
	runtime.SetFinalizer(obj, (*TasukiGap).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TasukiGap) WarmupPeriod() int {
	r := int(C.wickra_tasuki_gap_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TasukiGap) IsReady() bool {
	r := bool(C.wickra_tasuki_gap_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TasukiGap) Name() string {
	r := C.GoString(C.wickra_tasuki_gap_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TasukiGap) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_tasuki_gap_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TasukiGap) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_tasuki_gap_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TasukiGap) Reset() {
	C.wickra_tasuki_gap_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TasukiGap) Close() {
	if ind.handle != nil {
		C.wickra_tasuki_gap_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TdCamouflage wraps the TdCamouflage indicator over the Wickra C ABI.
type TdCamouflage struct {
	handle *C.struct_TdCamouflage
}

// NewTdCamouflage constructs a TdCamouflage. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTdCamouflage() (*TdCamouflage, error) {
	ptr := C.wickra_td_camouflage_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TdCamouflage{handle: ptr}
	runtime.SetFinalizer(obj, (*TdCamouflage).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TdCamouflage) WarmupPeriod() int {
	r := int(C.wickra_td_camouflage_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TdCamouflage) IsReady() bool {
	r := bool(C.wickra_td_camouflage_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TdCamouflage) Name() string {
	r := C.GoString(C.wickra_td_camouflage_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TdCamouflage) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_td_camouflage_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TdCamouflage) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_td_camouflage_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TdCamouflage) Reset() {
	C.wickra_td_camouflage_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TdCamouflage) Close() {
	if ind.handle != nil {
		C.wickra_td_camouflage_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TdClop wraps the TdClop indicator over the Wickra C ABI.
type TdClop struct {
	handle *C.struct_TdClop
}

// NewTdClop constructs a TdClop. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTdClop() (*TdClop, error) {
	ptr := C.wickra_td_clop_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TdClop{handle: ptr}
	runtime.SetFinalizer(obj, (*TdClop).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TdClop) WarmupPeriod() int {
	r := int(C.wickra_td_clop_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TdClop) IsReady() bool {
	r := bool(C.wickra_td_clop_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TdClop) Name() string {
	r := C.GoString(C.wickra_td_clop_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TdClop) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_td_clop_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TdClop) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_td_clop_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TdClop) Reset() {
	C.wickra_td_clop_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TdClop) Close() {
	if ind.handle != nil {
		C.wickra_td_clop_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TdClopwin wraps the TdClopwin indicator over the Wickra C ABI.
type TdClopwin struct {
	handle *C.struct_TdClopwin
}

// NewTdClopwin constructs a TdClopwin. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTdClopwin() (*TdClopwin, error) {
	ptr := C.wickra_td_clopwin_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TdClopwin{handle: ptr}
	runtime.SetFinalizer(obj, (*TdClopwin).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TdClopwin) WarmupPeriod() int {
	r := int(C.wickra_td_clopwin_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TdClopwin) IsReady() bool {
	r := bool(C.wickra_td_clopwin_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TdClopwin) Name() string {
	r := C.GoString(C.wickra_td_clopwin_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TdClopwin) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_td_clopwin_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TdClopwin) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_td_clopwin_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TdClopwin) Reset() {
	C.wickra_td_clopwin_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TdClopwin) Close() {
	if ind.handle != nil {
		C.wickra_td_clopwin_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TdCombo wraps the TdCombo indicator over the Wickra C ABI.
type TdCombo struct {
	handle *C.struct_TdCombo
}

// NewTdCombo constructs a TdCombo. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTdCombo(setupLookback int, setupTarget int, countdownLookback int, countdownTarget int) (*TdCombo, error) {
	ptr := C.wickra_td_combo_new(C.uintptr_t(setupLookback), C.uintptr_t(setupTarget), C.uintptr_t(countdownLookback), C.uintptr_t(countdownTarget))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TdCombo{handle: ptr}
	runtime.SetFinalizer(obj, (*TdCombo).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TdCombo) WarmupPeriod() int {
	r := int(C.wickra_td_combo_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TdCombo) IsReady() bool {
	r := bool(C.wickra_td_combo_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TdCombo) Name() string {
	r := C.GoString(C.wickra_td_combo_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TdCombo) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_td_combo_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TdCombo) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_td_combo_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TdCombo) Reset() {
	C.wickra_td_combo_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TdCombo) Close() {
	if ind.handle != nil {
		C.wickra_td_combo_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TdCountdown wraps the TdCountdown indicator over the Wickra C ABI.
type TdCountdown struct {
	handle *C.struct_TdCountdown
}

// NewTdCountdown constructs a TdCountdown. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTdCountdown(setupLookback int, setupTarget int, countdownLookback int, countdownTarget int) (*TdCountdown, error) {
	ptr := C.wickra_td_countdown_new(C.uintptr_t(setupLookback), C.uintptr_t(setupTarget), C.uintptr_t(countdownLookback), C.uintptr_t(countdownTarget))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TdCountdown{handle: ptr}
	runtime.SetFinalizer(obj, (*TdCountdown).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TdCountdown) WarmupPeriod() int {
	r := int(C.wickra_td_countdown_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TdCountdown) IsReady() bool {
	r := bool(C.wickra_td_countdown_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TdCountdown) Name() string {
	r := C.GoString(C.wickra_td_countdown_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TdCountdown) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_td_countdown_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TdCountdown) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_td_countdown_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TdCountdown) Reset() {
	C.wickra_td_countdown_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TdCountdown) Close() {
	if ind.handle != nil {
		C.wickra_td_countdown_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TdDWave wraps the TdDWave indicator over the Wickra C ABI.
type TdDWave struct {
	handle *C.struct_TdDWave
}

// NewTdDWave constructs a TdDWave. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTdDWave(strength int) (*TdDWave, error) {
	ptr := C.wickra_td_d_wave_new(C.uintptr_t(strength))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TdDWave{handle: ptr}
	runtime.SetFinalizer(obj, (*TdDWave).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TdDWave) WarmupPeriod() int {
	r := int(C.wickra_td_d_wave_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TdDWave) IsReady() bool {
	r := bool(C.wickra_td_d_wave_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TdDWave) Name() string {
	r := C.GoString(C.wickra_td_d_wave_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TdDWave) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_td_d_wave_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TdDWave) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_td_d_wave_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TdDWave) Reset() {
	C.wickra_td_d_wave_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TdDWave) Close() {
	if ind.handle != nil {
		C.wickra_td_d_wave_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TdDeMarker wraps the TdDeMarker indicator over the Wickra C ABI.
type TdDeMarker struct {
	handle *C.struct_TdDeMarker
}

// NewTdDeMarker constructs a TdDeMarker. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTdDeMarker(period int) (*TdDeMarker, error) {
	ptr := C.wickra_td_de_marker_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TdDeMarker{handle: ptr}
	runtime.SetFinalizer(obj, (*TdDeMarker).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TdDeMarker) WarmupPeriod() int {
	r := int(C.wickra_td_de_marker_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TdDeMarker) IsReady() bool {
	r := bool(C.wickra_td_de_marker_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TdDeMarker) Name() string {
	r := C.GoString(C.wickra_td_de_marker_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TdDeMarker) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_td_de_marker_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TdDeMarker) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_td_de_marker_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TdDeMarker) Reset() {
	C.wickra_td_de_marker_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TdDeMarker) Close() {
	if ind.handle != nil {
		C.wickra_td_de_marker_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TdDifferential wraps the TdDifferential indicator over the Wickra C ABI.
type TdDifferential struct {
	handle *C.struct_TdDifferential
}

// NewTdDifferential constructs a TdDifferential. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTdDifferential() (*TdDifferential, error) {
	ptr := C.wickra_td_differential_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TdDifferential{handle: ptr}
	runtime.SetFinalizer(obj, (*TdDifferential).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TdDifferential) WarmupPeriod() int {
	r := int(C.wickra_td_differential_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TdDifferential) IsReady() bool {
	r := bool(C.wickra_td_differential_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TdDifferential) Name() string {
	r := C.GoString(C.wickra_td_differential_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TdDifferential) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_td_differential_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TdDifferential) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_td_differential_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TdDifferential) Reset() {
	C.wickra_td_differential_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TdDifferential) Close() {
	if ind.handle != nil {
		C.wickra_td_differential_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TdLines wraps the TdLines indicator over the Wickra C ABI.
type TdLines struct {
	handle *C.struct_TdLines
}

// NewTdLines constructs a TdLines. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTdLines(lookback int, target int) (*TdLines, error) {
	ptr := C.wickra_td_lines_new(C.uintptr_t(lookback), C.uintptr_t(target))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TdLines{handle: ptr}
	runtime.SetFinalizer(obj, (*TdLines).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TdLines) WarmupPeriod() int {
	r := int(C.wickra_td_lines_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TdLines) IsReady() bool {
	r := bool(C.wickra_td_lines_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TdLines) Name() string {
	r := C.GoString(C.wickra_td_lines_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *TdLines) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (TdLinesOutput, bool) {
	var out C.struct_WickraTdLinesOutput
	ok := bool(C.wickra_td_lines_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return TdLinesOutput{}, false
	}
	return TdLinesOutput{float64(out.resistance), float64(out.support)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TdLines) Reset() {
	C.wickra_td_lines_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TdLines) Close() {
	if ind.handle != nil {
		C.wickra_td_lines_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TdMovingAverage wraps the TdMovingAverage indicator over the Wickra C ABI.
type TdMovingAverage struct {
	handle *C.struct_TdMovingAverage
}

// NewTdMovingAverage constructs a TdMovingAverage. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTdMovingAverage(periodSt1 int, periodSt2 int) (*TdMovingAverage, error) {
	ptr := C.wickra_td_moving_average_new(C.uintptr_t(periodSt1), C.uintptr_t(periodSt2))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TdMovingAverage{handle: ptr}
	runtime.SetFinalizer(obj, (*TdMovingAverage).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TdMovingAverage) WarmupPeriod() int {
	r := int(C.wickra_td_moving_average_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TdMovingAverage) IsReady() bool {
	r := bool(C.wickra_td_moving_average_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TdMovingAverage) Name() string {
	r := C.GoString(C.wickra_td_moving_average_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *TdMovingAverage) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (TdMovingAverageOutput, bool) {
	var out C.struct_WickraTdMovingAverageOutput
	ok := bool(C.wickra_td_moving_average_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return TdMovingAverageOutput{}, false
	}
	return TdMovingAverageOutput{float64(out.st1), float64(out.st2)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TdMovingAverage) Reset() {
	C.wickra_td_moving_average_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TdMovingAverage) Close() {
	if ind.handle != nil {
		C.wickra_td_moving_average_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TdOpen wraps the TdOpen indicator over the Wickra C ABI.
type TdOpen struct {
	handle *C.struct_TdOpen
}

// NewTdOpen constructs a TdOpen. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTdOpen() (*TdOpen, error) {
	ptr := C.wickra_td_open_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TdOpen{handle: ptr}
	runtime.SetFinalizer(obj, (*TdOpen).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TdOpen) WarmupPeriod() int {
	r := int(C.wickra_td_open_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TdOpen) IsReady() bool {
	r := bool(C.wickra_td_open_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TdOpen) Name() string {
	r := C.GoString(C.wickra_td_open_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TdOpen) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_td_open_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TdOpen) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_td_open_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TdOpen) Reset() {
	C.wickra_td_open_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TdOpen) Close() {
	if ind.handle != nil {
		C.wickra_td_open_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TdPressure wraps the TdPressure indicator over the Wickra C ABI.
type TdPressure struct {
	handle *C.struct_TdPressure
}

// NewTdPressure constructs a TdPressure. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTdPressure(period int) (*TdPressure, error) {
	ptr := C.wickra_td_pressure_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TdPressure{handle: ptr}
	runtime.SetFinalizer(obj, (*TdPressure).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TdPressure) WarmupPeriod() int {
	r := int(C.wickra_td_pressure_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TdPressure) IsReady() bool {
	r := bool(C.wickra_td_pressure_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TdPressure) Name() string {
	r := C.GoString(C.wickra_td_pressure_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TdPressure) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_td_pressure_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TdPressure) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_td_pressure_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TdPressure) Reset() {
	C.wickra_td_pressure_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TdPressure) Close() {
	if ind.handle != nil {
		C.wickra_td_pressure_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TdPropulsion wraps the TdPropulsion indicator over the Wickra C ABI.
type TdPropulsion struct {
	handle *C.struct_TdPropulsion
}

// NewTdPropulsion constructs a TdPropulsion. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTdPropulsion() (*TdPropulsion, error) {
	ptr := C.wickra_td_propulsion_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TdPropulsion{handle: ptr}
	runtime.SetFinalizer(obj, (*TdPropulsion).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TdPropulsion) WarmupPeriod() int {
	r := int(C.wickra_td_propulsion_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TdPropulsion) IsReady() bool {
	r := bool(C.wickra_td_propulsion_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TdPropulsion) Name() string {
	r := C.GoString(C.wickra_td_propulsion_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TdPropulsion) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_td_propulsion_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TdPropulsion) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_td_propulsion_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TdPropulsion) Reset() {
	C.wickra_td_propulsion_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TdPropulsion) Close() {
	if ind.handle != nil {
		C.wickra_td_propulsion_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TdRangeProjection wraps the TdRangeProjection indicator over the Wickra C ABI.
type TdRangeProjection struct {
	handle *C.struct_TdRangeProjection
}

// NewTdRangeProjection constructs a TdRangeProjection. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTdRangeProjection() (*TdRangeProjection, error) {
	ptr := C.wickra_td_range_projection_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TdRangeProjection{handle: ptr}
	runtime.SetFinalizer(obj, (*TdRangeProjection).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TdRangeProjection) WarmupPeriod() int {
	r := int(C.wickra_td_range_projection_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TdRangeProjection) IsReady() bool {
	r := bool(C.wickra_td_range_projection_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TdRangeProjection) Name() string {
	r := C.GoString(C.wickra_td_range_projection_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *TdRangeProjection) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (TdRangeProjectionOutput, bool) {
	var out C.struct_WickraTdRangeProjectionOutput
	ok := bool(C.wickra_td_range_projection_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return TdRangeProjectionOutput{}, false
	}
	return TdRangeProjectionOutput{float64(out.high), float64(out.low)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TdRangeProjection) Reset() {
	C.wickra_td_range_projection_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TdRangeProjection) Close() {
	if ind.handle != nil {
		C.wickra_td_range_projection_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TdRei wraps the TdRei indicator over the Wickra C ABI.
type TdRei struct {
	handle *C.struct_TdRei
}

// NewTdRei constructs a TdRei. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTdRei(period int) (*TdRei, error) {
	ptr := C.wickra_td_rei_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TdRei{handle: ptr}
	runtime.SetFinalizer(obj, (*TdRei).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TdRei) WarmupPeriod() int {
	r := int(C.wickra_td_rei_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TdRei) IsReady() bool {
	r := bool(C.wickra_td_rei_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TdRei) Name() string {
	r := C.GoString(C.wickra_td_rei_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TdRei) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_td_rei_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TdRei) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_td_rei_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TdRei) Reset() {
	C.wickra_td_rei_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TdRei) Close() {
	if ind.handle != nil {
		C.wickra_td_rei_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TdRiskLevel wraps the TdRiskLevel indicator over the Wickra C ABI.
type TdRiskLevel struct {
	handle *C.struct_TdRiskLevel
}

// NewTdRiskLevel constructs a TdRiskLevel. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTdRiskLevel(lookback int, target int) (*TdRiskLevel, error) {
	ptr := C.wickra_td_risk_level_new(C.uintptr_t(lookback), C.uintptr_t(target))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TdRiskLevel{handle: ptr}
	runtime.SetFinalizer(obj, (*TdRiskLevel).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TdRiskLevel) WarmupPeriod() int {
	r := int(C.wickra_td_risk_level_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TdRiskLevel) IsReady() bool {
	r := bool(C.wickra_td_risk_level_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TdRiskLevel) Name() string {
	r := C.GoString(C.wickra_td_risk_level_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *TdRiskLevel) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (TdRiskLevelOutput, bool) {
	var out C.struct_WickraTdRiskLevelOutput
	ok := bool(C.wickra_td_risk_level_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return TdRiskLevelOutput{}, false
	}
	return TdRiskLevelOutput{float64(out.buy_risk), float64(out.sell_risk)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TdRiskLevel) Reset() {
	C.wickra_td_risk_level_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TdRiskLevel) Close() {
	if ind.handle != nil {
		C.wickra_td_risk_level_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TdSequential wraps the TdSequential indicator over the Wickra C ABI.
type TdSequential struct {
	handle *C.struct_TdSequential
}

// NewTdSequential constructs a TdSequential. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTdSequential(setupLookback int, setupTarget int, countdownLookback int, countdownTarget int) (*TdSequential, error) {
	ptr := C.wickra_td_sequential_new(C.uintptr_t(setupLookback), C.uintptr_t(setupTarget), C.uintptr_t(countdownLookback), C.uintptr_t(countdownTarget))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TdSequential{handle: ptr}
	runtime.SetFinalizer(obj, (*TdSequential).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TdSequential) WarmupPeriod() int {
	r := int(C.wickra_td_sequential_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TdSequential) IsReady() bool {
	r := bool(C.wickra_td_sequential_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TdSequential) Name() string {
	r := C.GoString(C.wickra_td_sequential_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *TdSequential) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (TdSequentialOutput, bool) {
	var out C.struct_WickraTdSequentialOutput
	ok := bool(C.wickra_td_sequential_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return TdSequentialOutput{}, false
	}
	return TdSequentialOutput{float64(out.setup), float64(out.countdown), float64(out.direction)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TdSequential) Reset() {
	C.wickra_td_sequential_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TdSequential) Close() {
	if ind.handle != nil {
		C.wickra_td_sequential_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TdSetup wraps the TdSetup indicator over the Wickra C ABI.
type TdSetup struct {
	handle *C.struct_TdSetup
}

// NewTdSetup constructs a TdSetup. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTdSetup(lookback int, target int) (*TdSetup, error) {
	ptr := C.wickra_td_setup_new(C.uintptr_t(lookback), C.uintptr_t(target))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TdSetup{handle: ptr}
	runtime.SetFinalizer(obj, (*TdSetup).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TdSetup) WarmupPeriod() int {
	r := int(C.wickra_td_setup_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TdSetup) IsReady() bool {
	r := bool(C.wickra_td_setup_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TdSetup) Name() string {
	r := C.GoString(C.wickra_td_setup_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TdSetup) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_td_setup_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TdSetup) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_td_setup_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TdSetup) Reset() {
	C.wickra_td_setup_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TdSetup) Close() {
	if ind.handle != nil {
		C.wickra_td_setup_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TdTrap wraps the TdTrap indicator over the Wickra C ABI.
type TdTrap struct {
	handle *C.struct_TdTrap
}

// NewTdTrap constructs a TdTrap. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTdTrap() (*TdTrap, error) {
	ptr := C.wickra_td_trap_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TdTrap{handle: ptr}
	runtime.SetFinalizer(obj, (*TdTrap).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TdTrap) WarmupPeriod() int {
	r := int(C.wickra_td_trap_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TdTrap) IsReady() bool {
	r := bool(C.wickra_td_trap_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TdTrap) Name() string {
	r := C.GoString(C.wickra_td_trap_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TdTrap) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_td_trap_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TdTrap) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_td_trap_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TdTrap) Reset() {
	C.wickra_td_trap_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TdTrap) Close() {
	if ind.handle != nil {
		C.wickra_td_trap_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Tema wraps the Tema indicator over the Wickra C ABI.
type Tema struct {
	handle *C.struct_Tema
}

// NewTema constructs a Tema. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTema(period int) (*Tema, error) {
	ptr := C.wickra_tema_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Tema{handle: ptr}
	runtime.SetFinalizer(obj, (*Tema).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Tema) WarmupPeriod() int {
	r := int(C.wickra_tema_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Tema) IsReady() bool {
	r := bool(C.wickra_tema_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Tema) Name() string {
	r := C.GoString(C.wickra_tema_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Tema) Update(value float64) float64 {
	r := float64(C.wickra_tema_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Tema) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_tema_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Tema) Reset() {
	C.wickra_tema_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Tema) Close() {
	if ind.handle != nil {
		C.wickra_tema_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TermStructureBasis wraps the TermStructureBasis indicator over the Wickra C ABI.
type TermStructureBasis struct {
	handle *C.struct_TermStructureBasis
}

// NewTermStructureBasis constructs a TermStructureBasis. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTermStructureBasis() (*TermStructureBasis, error) {
	ptr := C.wickra_term_structure_basis_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TermStructureBasis{handle: ptr}
	runtime.SetFinalizer(obj, (*TermStructureBasis).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TermStructureBasis) WarmupPeriod() int {
	r := int(C.wickra_term_structure_basis_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TermStructureBasis) IsReady() bool {
	r := bool(C.wickra_term_structure_basis_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TermStructureBasis) Name() string {
	r := C.GoString(C.wickra_term_structure_basis_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TermStructureBasis) Update(fundingRate float64, markPrice float64, indexPrice float64, futuresPrice float64, openInterest float64, longSize float64, shortSize float64, takerBuyVolume float64, takerSellVolume float64, longLiquidation float64, shortLiquidation float64, timestamp int64) float64 {
	r := float64(C.wickra_term_structure_basis_update(ind.handle, C.double(fundingRate), C.double(markPrice), C.double(indexPrice), C.double(futuresPrice), C.double(openInterest), C.double(longSize), C.double(shortSize), C.double(takerBuyVolume), C.double(takerSellVolume), C.double(longLiquidation), C.double(shortLiquidation), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TermStructureBasis) Reset() {
	C.wickra_term_structure_basis_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TermStructureBasis) Close() {
	if ind.handle != nil {
		C.wickra_term_structure_basis_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ThreeDrives wraps the ThreeDrives indicator over the Wickra C ABI.
type ThreeDrives struct {
	handle *C.struct_ThreeDrives
}

// NewThreeDrives constructs a ThreeDrives. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewThreeDrives() (*ThreeDrives, error) {
	ptr := C.wickra_three_drives_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ThreeDrives{handle: ptr}
	runtime.SetFinalizer(obj, (*ThreeDrives).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ThreeDrives) WarmupPeriod() int {
	r := int(C.wickra_three_drives_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ThreeDrives) IsReady() bool {
	r := bool(C.wickra_three_drives_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ThreeDrives) Name() string {
	r := C.GoString(C.wickra_three_drives_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ThreeDrives) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_three_drives_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ThreeDrives) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_three_drives_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ThreeDrives) Reset() {
	C.wickra_three_drives_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ThreeDrives) Close() {
	if ind.handle != nil {
		C.wickra_three_drives_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ThreeInside wraps the ThreeInside indicator over the Wickra C ABI.
type ThreeInside struct {
	handle *C.struct_ThreeInside
}

// NewThreeInside constructs a ThreeInside. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewThreeInside() (*ThreeInside, error) {
	ptr := C.wickra_three_inside_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ThreeInside{handle: ptr}
	runtime.SetFinalizer(obj, (*ThreeInside).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ThreeInside) WarmupPeriod() int {
	r := int(C.wickra_three_inside_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ThreeInside) IsReady() bool {
	r := bool(C.wickra_three_inside_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ThreeInside) Name() string {
	r := C.GoString(C.wickra_three_inside_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ThreeInside) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_three_inside_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ThreeInside) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_three_inside_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ThreeInside) Reset() {
	C.wickra_three_inside_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ThreeInside) Close() {
	if ind.handle != nil {
		C.wickra_three_inside_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ThreeLineBreak wraps the ThreeLineBreak indicator over the Wickra C ABI.
type ThreeLineBreak struct {
	handle *C.struct_ThreeLineBreak
}

// NewThreeLineBreak constructs a ThreeLineBreak. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewThreeLineBreak(lines int) (*ThreeLineBreak, error) {
	ptr := C.wickra_three_line_break_new(C.uintptr_t(lines))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ThreeLineBreak{handle: ptr}
	runtime.SetFinalizer(obj, (*ThreeLineBreak).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ThreeLineBreak) WarmupPeriod() int {
	r := int(C.wickra_three_line_break_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ThreeLineBreak) IsReady() bool {
	r := bool(C.wickra_three_line_break_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ThreeLineBreak) Name() string {
	r := C.GoString(C.wickra_three_line_break_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ThreeLineBreak) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_three_line_break_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ThreeLineBreak) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_three_line_break_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ThreeLineBreak) Reset() {
	C.wickra_three_line_break_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ThreeLineBreak) Close() {
	if ind.handle != nil {
		C.wickra_three_line_break_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ThreeLineBreakBars wraps the ThreeLineBreakBars indicator over the Wickra C ABI.
type ThreeLineBreakBars struct {
	handle *C.struct_ThreeLineBreakBars
}

// NewThreeLineBreakBars constructs a ThreeLineBreakBars. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewThreeLineBreakBars(lines int) (*ThreeLineBreakBars, error) {
	ptr := C.wickra_three_line_break_bars_new(C.uintptr_t(lines))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ThreeLineBreakBars{handle: ptr}
	runtime.SetFinalizer(obj, (*ThreeLineBreakBars).Close)
	return obj, nil
}

// Name returns the indicator's canonical name.
func (ind *ThreeLineBreakBars) Name() string {
	r := C.GoString(C.wickra_three_line_break_bars_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one candle and returns any bars completed by it
// (a single candle may complete several).
func (ind *ThreeLineBreakBars) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) []LineBreakBar {
	const capacity = 64
	var buf [capacity]C.struct_WickraLineBreakBar
	n := int(C.wickra_three_line_break_bars_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &buf[0], C.uintptr_t(capacity)))
	runtime.KeepAlive(ind)
	if n <= 0 {
		return nil
	}
	out := make([]LineBreakBar, n)
	for i := 0; i < n; i++ {
		out[i] = LineBreakBar{float64(buf[i].open), float64(buf[i].close), int8(buf[i].direction)}
	}
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ThreeLineBreakBars) Reset() {
	C.wickra_three_line_break_bars_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ThreeLineBreakBars) Close() {
	if ind.handle != nil {
		C.wickra_three_line_break_bars_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ThreeLineStrike wraps the ThreeLineStrike indicator over the Wickra C ABI.
type ThreeLineStrike struct {
	handle *C.struct_ThreeLineStrike
}

// NewThreeLineStrike constructs a ThreeLineStrike. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewThreeLineStrike() (*ThreeLineStrike, error) {
	ptr := C.wickra_three_line_strike_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ThreeLineStrike{handle: ptr}
	runtime.SetFinalizer(obj, (*ThreeLineStrike).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ThreeLineStrike) WarmupPeriod() int {
	r := int(C.wickra_three_line_strike_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ThreeLineStrike) IsReady() bool {
	r := bool(C.wickra_three_line_strike_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ThreeLineStrike) Name() string {
	r := C.GoString(C.wickra_three_line_strike_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ThreeLineStrike) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_three_line_strike_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ThreeLineStrike) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_three_line_strike_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ThreeLineStrike) Reset() {
	C.wickra_three_line_strike_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ThreeLineStrike) Close() {
	if ind.handle != nil {
		C.wickra_three_line_strike_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ThreeOutside wraps the ThreeOutside indicator over the Wickra C ABI.
type ThreeOutside struct {
	handle *C.struct_ThreeOutside
}

// NewThreeOutside constructs a ThreeOutside. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewThreeOutside() (*ThreeOutside, error) {
	ptr := C.wickra_three_outside_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ThreeOutside{handle: ptr}
	runtime.SetFinalizer(obj, (*ThreeOutside).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ThreeOutside) WarmupPeriod() int {
	r := int(C.wickra_three_outside_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ThreeOutside) IsReady() bool {
	r := bool(C.wickra_three_outside_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ThreeOutside) Name() string {
	r := C.GoString(C.wickra_three_outside_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ThreeOutside) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_three_outside_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ThreeOutside) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_three_outside_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ThreeOutside) Reset() {
	C.wickra_three_outside_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ThreeOutside) Close() {
	if ind.handle != nil {
		C.wickra_three_outside_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ThreeSoldiersOrCrows wraps the ThreeSoldiersOrCrows indicator over the Wickra C ABI.
type ThreeSoldiersOrCrows struct {
	handle *C.struct_ThreeSoldiersOrCrows
}

// NewThreeSoldiersOrCrows constructs a ThreeSoldiersOrCrows. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewThreeSoldiersOrCrows() (*ThreeSoldiersOrCrows, error) {
	ptr := C.wickra_three_soldiers_or_crows_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ThreeSoldiersOrCrows{handle: ptr}
	runtime.SetFinalizer(obj, (*ThreeSoldiersOrCrows).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ThreeSoldiersOrCrows) WarmupPeriod() int {
	r := int(C.wickra_three_soldiers_or_crows_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ThreeSoldiersOrCrows) IsReady() bool {
	r := bool(C.wickra_three_soldiers_or_crows_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ThreeSoldiersOrCrows) Name() string {
	r := C.GoString(C.wickra_three_soldiers_or_crows_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ThreeSoldiersOrCrows) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_three_soldiers_or_crows_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ThreeSoldiersOrCrows) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_three_soldiers_or_crows_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ThreeSoldiersOrCrows) Reset() {
	C.wickra_three_soldiers_or_crows_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ThreeSoldiersOrCrows) Close() {
	if ind.handle != nil {
		C.wickra_three_soldiers_or_crows_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ThreeStarsInSouth wraps the ThreeStarsInSouth indicator over the Wickra C ABI.
type ThreeStarsInSouth struct {
	handle *C.struct_ThreeStarsInSouth
}

// NewThreeStarsInSouth constructs a ThreeStarsInSouth. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewThreeStarsInSouth() (*ThreeStarsInSouth, error) {
	ptr := C.wickra_three_stars_in_south_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ThreeStarsInSouth{handle: ptr}
	runtime.SetFinalizer(obj, (*ThreeStarsInSouth).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ThreeStarsInSouth) WarmupPeriod() int {
	r := int(C.wickra_three_stars_in_south_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ThreeStarsInSouth) IsReady() bool {
	r := bool(C.wickra_three_stars_in_south_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ThreeStarsInSouth) Name() string {
	r := C.GoString(C.wickra_three_stars_in_south_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ThreeStarsInSouth) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_three_stars_in_south_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ThreeStarsInSouth) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_three_stars_in_south_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ThreeStarsInSouth) Reset() {
	C.wickra_three_stars_in_south_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ThreeStarsInSouth) Close() {
	if ind.handle != nil {
		C.wickra_three_stars_in_south_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Thrusting wraps the Thrusting indicator over the Wickra C ABI.
type Thrusting struct {
	handle *C.struct_Thrusting
}

// NewThrusting constructs a Thrusting. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewThrusting() (*Thrusting, error) {
	ptr := C.wickra_thrusting_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Thrusting{handle: ptr}
	runtime.SetFinalizer(obj, (*Thrusting).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Thrusting) WarmupPeriod() int {
	r := int(C.wickra_thrusting_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Thrusting) IsReady() bool {
	r := bool(C.wickra_thrusting_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Thrusting) Name() string {
	r := C.GoString(C.wickra_thrusting_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Thrusting) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_thrusting_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Thrusting) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_thrusting_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Thrusting) Reset() {
	C.wickra_thrusting_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Thrusting) Close() {
	if ind.handle != nil {
		C.wickra_thrusting_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TickAggregator wraps the TickAggregator indicator over the Wickra C ABI.
type TickAggregator struct {
	handle *C.struct_TickAggregator
}

// NewTickAggregator constructs a TickAggregator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTickAggregator(bucket int64, gapFill bool) (*TickAggregator, error) {
	ptr := C.wickra_tick_aggregator_new(C.int64_t(bucket), C.bool(gapFill))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TickAggregator{handle: ptr}
	runtime.SetFinalizer(obj, (*TickAggregator).Close)
	return obj, nil
}

// Push feeds one trade tick and returns the candles it closed (none while
// the open bar grows, one per closed bucket, plus gap-fill placeholders).
func (ind *TickAggregator) Push(price float64, size float64, timestamp int64) []Candle {
	n := int(C.wickra_tick_aggregator_push(ind.handle, C.double(price), C.double(size), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	if n <= 0 {
		return nil
	}
	buf := make([]C.struct_WickraCandle, n)
	C.wickra_tick_aggregator_drain(ind.handle, &buf[0], C.uintptr_t(n))
	runtime.KeepAlive(ind)
	out := make([]Candle, n)
	for i := 0; i < n; i++ {
		out[i] = Candle{float64(buf[i].open), float64(buf[i].high), float64(buf[i].low), float64(buf[i].close), float64(buf[i].volume), int64(buf[i].timestamp)}
	}
	return out
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TickAggregator) Close() {
	if ind.handle != nil {
		C.wickra_tick_aggregator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TickBars wraps the TickBars indicator over the Wickra C ABI.
type TickBars struct {
	handle *C.struct_TickBars
}

// NewTickBars constructs a TickBars. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTickBars(ticks int) (*TickBars, error) {
	ptr := C.wickra_tick_bars_new(C.uintptr_t(ticks))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TickBars{handle: ptr}
	runtime.SetFinalizer(obj, (*TickBars).Close)
	return obj, nil
}

// Name returns the indicator's canonical name.
func (ind *TickBars) Name() string {
	r := C.GoString(C.wickra_tick_bars_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one candle and returns any bars completed by it
// (a single candle may complete several).
func (ind *TickBars) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) []TickBar {
	const capacity = 64
	var buf [capacity]C.struct_WickraTickBar
	n := int(C.wickra_tick_bars_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &buf[0], C.uintptr_t(capacity)))
	runtime.KeepAlive(ind)
	if n <= 0 {
		return nil
	}
	out := make([]TickBar, n)
	for i := 0; i < n; i++ {
		out[i] = TickBar{float64(buf[i].open), float64(buf[i].high), float64(buf[i].low), float64(buf[i].close), float64(buf[i].volume)}
	}
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TickBars) Reset() {
	C.wickra_tick_bars_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TickBars) Close() {
	if ind.handle != nil {
		C.wickra_tick_bars_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TickIndex wraps the TickIndex indicator over the Wickra C ABI.
type TickIndex struct {
	handle *C.struct_TickIndex
}

// NewTickIndex constructs a TickIndex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTickIndex() (*TickIndex, error) {
	ptr := C.wickra_tick_index_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TickIndex{handle: ptr}
	runtime.SetFinalizer(obj, (*TickIndex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TickIndex) WarmupPeriod() int {
	r := int(C.wickra_tick_index_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TickIndex) IsReady() bool {
	r := bool(C.wickra_tick_index_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TickIndex) Name() string {
	r := C.GoString(C.wickra_tick_index_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *TickIndex) Update(change []float64, volume []float64, newHigh []bool, newLow []bool, aboveMa []bool, onBuySignal []bool, timestamp int64) float64 {
	if len(volume) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newHigh) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newLow) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(aboveMa) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(onBuySignal) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_tick_index_update(ind.handle, (*C.double)(unsafe.Pointer(&change[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.bool)(unsafe.Pointer(&newHigh[0])), (*C.bool)(unsafe.Pointer(&newLow[0])), (*C.bool)(unsafe.Pointer(&aboveMa[0])), (*C.bool)(unsafe.Pointer(&onBuySignal[0])), C.uintptr_t(len(change)), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(change)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(newHigh)
	runtime.KeepAlive(newLow)
	runtime.KeepAlive(aboveMa)
	runtime.KeepAlive(onBuySignal)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TickIndex) Reset() {
	C.wickra_tick_index_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TickIndex) Close() {
	if ind.handle != nil {
		C.wickra_tick_index_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Tii wraps the Tii indicator over the Wickra C ABI.
type Tii struct {
	handle *C.struct_Tii
}

// NewTii constructs a Tii. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTii(smaPeriod int, devPeriod int) (*Tii, error) {
	ptr := C.wickra_tii_new(C.uintptr_t(smaPeriod), C.uintptr_t(devPeriod))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Tii{handle: ptr}
	runtime.SetFinalizer(obj, (*Tii).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Tii) WarmupPeriod() int {
	r := int(C.wickra_tii_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Tii) IsReady() bool {
	r := bool(C.wickra_tii_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Tii) Name() string {
	r := C.GoString(C.wickra_tii_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Tii) Update(value float64) float64 {
	r := float64(C.wickra_tii_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Tii) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_tii_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Tii) Reset() {
	C.wickra_tii_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Tii) Close() {
	if ind.handle != nil {
		C.wickra_tii_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TimeBasedStop wraps the TimeBasedStop indicator over the Wickra C ABI.
type TimeBasedStop struct {
	handle *C.struct_TimeBasedStop
}

// NewTimeBasedStop constructs a TimeBasedStop. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTimeBasedStop(maxBars int) (*TimeBasedStop, error) {
	ptr := C.wickra_time_based_stop_new(C.uintptr_t(maxBars))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TimeBasedStop{handle: ptr}
	runtime.SetFinalizer(obj, (*TimeBasedStop).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TimeBasedStop) WarmupPeriod() int {
	r := int(C.wickra_time_based_stop_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TimeBasedStop) IsReady() bool {
	r := bool(C.wickra_time_based_stop_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TimeBasedStop) Name() string {
	r := C.GoString(C.wickra_time_based_stop_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TimeBasedStop) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_time_based_stop_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TimeBasedStop) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_time_based_stop_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TimeBasedStop) Reset() {
	C.wickra_time_based_stop_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TimeBasedStop) Close() {
	if ind.handle != nil {
		C.wickra_time_based_stop_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TimeOfDayReturnProfile wraps the TimeOfDayReturnProfile indicator over the Wickra C ABI.
type TimeOfDayReturnProfile struct {
	handle    *C.struct_TimeOfDayReturnProfile
	valuesCap int
}

// NewTimeOfDayReturnProfile constructs a TimeOfDayReturnProfile. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTimeOfDayReturnProfile(buckets int, utcOffsetMinutes int32) (*TimeOfDayReturnProfile, error) {
	ptr := C.wickra_time_of_day_return_profile_new(C.uintptr_t(buckets), C.int32_t(utcOffsetMinutes))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TimeOfDayReturnProfile{handle: ptr}
	obj.valuesCap = buckets
	runtime.SetFinalizer(obj, (*TimeOfDayReturnProfile).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TimeOfDayReturnProfile) WarmupPeriod() int {
	r := int(C.wickra_time_of_day_return_profile_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TimeOfDayReturnProfile) IsReady() bool {
	r := bool(C.wickra_time_of_day_return_profile_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TimeOfDayReturnProfile) Name() string {
	r := C.GoString(C.wickra_time_of_day_return_profile_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the profile values
// (ok is false during warmup).
func (ind *TimeOfDayReturnProfile) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) ([]float64, bool) {
	values := make([]float64, ind.valuesCap)
	n := int(C.wickra_time_of_day_return_profile_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), (*C.double)(unsafe.Pointer(&values[0])), C.uintptr_t(len(values))))
	runtime.KeepAlive(ind)
	if n < 0 {
		return nil, false
	}
	return values[:n], true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TimeOfDayReturnProfile) Reset() {
	C.wickra_time_of_day_return_profile_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TimeOfDayReturnProfile) Close() {
	if ind.handle != nil {
		C.wickra_time_of_day_return_profile_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TowerTopBottom wraps the TowerTopBottom indicator over the Wickra C ABI.
type TowerTopBottom struct {
	handle *C.struct_TowerTopBottom
}

// NewTowerTopBottom constructs a TowerTopBottom. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTowerTopBottom() (*TowerTopBottom, error) {
	ptr := C.wickra_tower_top_bottom_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TowerTopBottom{handle: ptr}
	runtime.SetFinalizer(obj, (*TowerTopBottom).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TowerTopBottom) WarmupPeriod() int {
	r := int(C.wickra_tower_top_bottom_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TowerTopBottom) IsReady() bool {
	r := bool(C.wickra_tower_top_bottom_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TowerTopBottom) Name() string {
	r := C.GoString(C.wickra_tower_top_bottom_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TowerTopBottom) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_tower_top_bottom_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TowerTopBottom) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_tower_top_bottom_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TowerTopBottom) Reset() {
	C.wickra_tower_top_bottom_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TowerTopBottom) Close() {
	if ind.handle != nil {
		C.wickra_tower_top_bottom_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TpoProfile wraps the TpoProfile indicator over the Wickra C ABI.
type TpoProfile struct {
	handle    *C.struct_TpoProfile
	valuesCap int
}

// NewTpoProfile constructs a TpoProfile. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTpoProfile(period int, binCount int) (*TpoProfile, error) {
	ptr := C.wickra_tpo_profile_new(C.uintptr_t(period), C.uintptr_t(binCount))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TpoProfile{handle: ptr}
	obj.valuesCap = binCount
	runtime.SetFinalizer(obj, (*TpoProfile).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TpoProfile) WarmupPeriod() int {
	r := int(C.wickra_tpo_profile_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TpoProfile) IsReady() bool {
	r := bool(C.wickra_tpo_profile_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TpoProfile) Name() string {
	r := C.GoString(C.wickra_tpo_profile_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the profile snapshot
// (ok is false during warmup).
func (ind *TpoProfile) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (TpoProfileOutputScalars, bool) {
	values := make([]float64, ind.valuesCap)
	var sc C.struct_WickraTpoProfileOutputScalars
	n := int(C.wickra_tpo_profile_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &sc, (*C.double)(unsafe.Pointer(&values[0])), C.uintptr_t(len(values))))
	runtime.KeepAlive(ind)
	if n < 0 {
		return TpoProfileOutputScalars{}, false
	}
	return TpoProfileOutputScalars{PriceLow: float64(sc.price_low), PriceHigh: float64(sc.price_high), Values: values[:n]}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TpoProfile) Reset() {
	C.wickra_tpo_profile_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TpoProfile) Close() {
	if ind.handle != nil {
		C.wickra_tpo_profile_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TradeImbalance wraps the TradeImbalance indicator over the Wickra C ABI.
type TradeImbalance struct {
	handle *C.struct_TradeImbalance
}

// NewTradeImbalance constructs a TradeImbalance. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTradeImbalance(window int) (*TradeImbalance, error) {
	ptr := C.wickra_trade_imbalance_new(C.uintptr_t(window))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TradeImbalance{handle: ptr}
	runtime.SetFinalizer(obj, (*TradeImbalance).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TradeImbalance) WarmupPeriod() int {
	r := int(C.wickra_trade_imbalance_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TradeImbalance) IsReady() bool {
	r := bool(C.wickra_trade_imbalance_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TradeImbalance) Name() string {
	r := C.GoString(C.wickra_trade_imbalance_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TradeImbalance) Update(price float64, size float64, isBuy bool, timestamp int64) float64 {
	r := float64(C.wickra_trade_imbalance_update(ind.handle, C.double(price), C.double(size), C.bool(isBuy), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TradeImbalance) Reset() {
	C.wickra_trade_imbalance_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TradeImbalance) Close() {
	if ind.handle != nil {
		C.wickra_trade_imbalance_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TradeSignAutocorrelation wraps the TradeSignAutocorrelation indicator over the Wickra C ABI.
type TradeSignAutocorrelation struct {
	handle *C.struct_TradeSignAutocorrelation
}

// NewTradeSignAutocorrelation constructs a TradeSignAutocorrelation. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTradeSignAutocorrelation(period int) (*TradeSignAutocorrelation, error) {
	ptr := C.wickra_trade_sign_autocorrelation_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TradeSignAutocorrelation{handle: ptr}
	runtime.SetFinalizer(obj, (*TradeSignAutocorrelation).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TradeSignAutocorrelation) WarmupPeriod() int {
	r := int(C.wickra_trade_sign_autocorrelation_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TradeSignAutocorrelation) IsReady() bool {
	r := bool(C.wickra_trade_sign_autocorrelation_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TradeSignAutocorrelation) Name() string {
	r := C.GoString(C.wickra_trade_sign_autocorrelation_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TradeSignAutocorrelation) Update(price float64, size float64, isBuy bool, timestamp int64) float64 {
	r := float64(C.wickra_trade_sign_autocorrelation_update(ind.handle, C.double(price), C.double(size), C.bool(isBuy), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TradeSignAutocorrelation) Reset() {
	C.wickra_trade_sign_autocorrelation_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TradeSignAutocorrelation) Close() {
	if ind.handle != nil {
		C.wickra_trade_sign_autocorrelation_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TradeVolumeIndex wraps the TradeVolumeIndex indicator over the Wickra C ABI.
type TradeVolumeIndex struct {
	handle *C.struct_TradeVolumeIndex
}

// NewTradeVolumeIndex constructs a TradeVolumeIndex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTradeVolumeIndex(minTick float64) (*TradeVolumeIndex, error) {
	ptr := C.wickra_trade_volume_index_new(C.double(minTick))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TradeVolumeIndex{handle: ptr}
	runtime.SetFinalizer(obj, (*TradeVolumeIndex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TradeVolumeIndex) WarmupPeriod() int {
	r := int(C.wickra_trade_volume_index_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TradeVolumeIndex) IsReady() bool {
	r := bool(C.wickra_trade_volume_index_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TradeVolumeIndex) Name() string {
	r := C.GoString(C.wickra_trade_volume_index_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TradeVolumeIndex) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_trade_volume_index_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TradeVolumeIndex) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_trade_volume_index_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TradeVolumeIndex) Reset() {
	C.wickra_trade_volume_index_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TradeVolumeIndex) Close() {
	if ind.handle != nil {
		C.wickra_trade_volume_index_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TrendLabel wraps the TrendLabel indicator over the Wickra C ABI.
type TrendLabel struct {
	handle *C.struct_TrendLabel
}

// NewTrendLabel constructs a TrendLabel. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTrendLabel(period int) (*TrendLabel, error) {
	ptr := C.wickra_trend_label_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TrendLabel{handle: ptr}
	runtime.SetFinalizer(obj, (*TrendLabel).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TrendLabel) WarmupPeriod() int {
	r := int(C.wickra_trend_label_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TrendLabel) IsReady() bool {
	r := bool(C.wickra_trend_label_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TrendLabel) Name() string {
	r := C.GoString(C.wickra_trend_label_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TrendLabel) Update(value float64) float64 {
	r := float64(C.wickra_trend_label_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TrendLabel) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_trend_label_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TrendLabel) Reset() {
	C.wickra_trend_label_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TrendLabel) Close() {
	if ind.handle != nil {
		C.wickra_trend_label_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TrendStrengthIndex wraps the TrendStrengthIndex indicator over the Wickra C ABI.
type TrendStrengthIndex struct {
	handle *C.struct_TrendStrengthIndex
}

// NewTrendStrengthIndex constructs a TrendStrengthIndex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTrendStrengthIndex(period int) (*TrendStrengthIndex, error) {
	ptr := C.wickra_trend_strength_index_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TrendStrengthIndex{handle: ptr}
	runtime.SetFinalizer(obj, (*TrendStrengthIndex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TrendStrengthIndex) WarmupPeriod() int {
	r := int(C.wickra_trend_strength_index_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TrendStrengthIndex) IsReady() bool {
	r := bool(C.wickra_trend_strength_index_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TrendStrengthIndex) Name() string {
	r := C.GoString(C.wickra_trend_strength_index_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TrendStrengthIndex) Update(value float64) float64 {
	r := float64(C.wickra_trend_strength_index_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TrendStrengthIndex) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_trend_strength_index_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TrendStrengthIndex) Reset() {
	C.wickra_trend_strength_index_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TrendStrengthIndex) Close() {
	if ind.handle != nil {
		C.wickra_trend_strength_index_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Trendflex wraps the Trendflex indicator over the Wickra C ABI.
type Trendflex struct {
	handle *C.struct_Trendflex
}

// NewTrendflex constructs a Trendflex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTrendflex(period int) (*Trendflex, error) {
	ptr := C.wickra_trendflex_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Trendflex{handle: ptr}
	runtime.SetFinalizer(obj, (*Trendflex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Trendflex) WarmupPeriod() int {
	r := int(C.wickra_trendflex_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Trendflex) IsReady() bool {
	r := bool(C.wickra_trendflex_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Trendflex) Name() string {
	r := C.GoString(C.wickra_trendflex_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Trendflex) Update(value float64) float64 {
	r := float64(C.wickra_trendflex_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Trendflex) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_trendflex_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Trendflex) Reset() {
	C.wickra_trendflex_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Trendflex) Close() {
	if ind.handle != nil {
		C.wickra_trendflex_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TreynorRatio wraps the TreynorRatio indicator over the Wickra C ABI.
type TreynorRatio struct {
	handle *C.struct_TreynorRatio
}

// NewTreynorRatio constructs a TreynorRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTreynorRatio(period int, riskFree float64) (*TreynorRatio, error) {
	ptr := C.wickra_treynor_ratio_new(C.uintptr_t(period), C.double(riskFree))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TreynorRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*TreynorRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TreynorRatio) WarmupPeriod() int {
	r := int(C.wickra_treynor_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TreynorRatio) IsReady() bool {
	r := bool(C.wickra_treynor_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TreynorRatio) Name() string {
	r := C.GoString(C.wickra_treynor_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TreynorRatio) Update(x float64, y float64) float64 {
	r := float64(C.wickra_treynor_ratio_update(ind.handle, C.double(x), C.double(y)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TreynorRatio) Batch(x []float64, y []float64) []float64 {
	n := len(x)
	if len(y) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_treynor_ratio_batch(ind.handle, (*C.double)(unsafe.Pointer(&x[0])), (*C.double)(unsafe.Pointer(&y[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(x)
	runtime.KeepAlive(y)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TreynorRatio) Reset() {
	C.wickra_treynor_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TreynorRatio) Close() {
	if ind.handle != nil {
		C.wickra_treynor_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Triangle wraps the Triangle indicator over the Wickra C ABI.
type Triangle struct {
	handle *C.struct_Triangle
}

// NewTriangle constructs a Triangle. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTriangle() (*Triangle, error) {
	ptr := C.wickra_triangle_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Triangle{handle: ptr}
	runtime.SetFinalizer(obj, (*Triangle).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Triangle) WarmupPeriod() int {
	r := int(C.wickra_triangle_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Triangle) IsReady() bool {
	r := bool(C.wickra_triangle_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Triangle) Name() string {
	r := C.GoString(C.wickra_triangle_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Triangle) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_triangle_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Triangle) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_triangle_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Triangle) Reset() {
	C.wickra_triangle_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Triangle) Close() {
	if ind.handle != nil {
		C.wickra_triangle_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Trima wraps the Trima indicator over the Wickra C ABI.
type Trima struct {
	handle *C.struct_Trima
}

// NewTrima constructs a Trima. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTrima(period int) (*Trima, error) {
	ptr := C.wickra_trima_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Trima{handle: ptr}
	runtime.SetFinalizer(obj, (*Trima).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Trima) WarmupPeriod() int {
	r := int(C.wickra_trima_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Trima) IsReady() bool {
	r := bool(C.wickra_trima_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Trima) Name() string {
	r := C.GoString(C.wickra_trima_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Trima) Update(value float64) float64 {
	r := float64(C.wickra_trima_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Trima) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_trima_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Trima) Reset() {
	C.wickra_trima_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Trima) Close() {
	if ind.handle != nil {
		C.wickra_trima_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Trin wraps the Trin indicator over the Wickra C ABI.
type Trin struct {
	handle *C.struct_Trin
}

// NewTrin constructs a Trin. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTrin() (*Trin, error) {
	ptr := C.wickra_trin_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Trin{handle: ptr}
	runtime.SetFinalizer(obj, (*Trin).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Trin) WarmupPeriod() int {
	r := int(C.wickra_trin_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Trin) IsReady() bool {
	r := bool(C.wickra_trin_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Trin) Name() string {
	r := C.GoString(C.wickra_trin_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *Trin) Update(change []float64, volume []float64, newHigh []bool, newLow []bool, aboveMa []bool, onBuySignal []bool, timestamp int64) float64 {
	if len(volume) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newHigh) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newLow) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(aboveMa) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(onBuySignal) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_trin_update(ind.handle, (*C.double)(unsafe.Pointer(&change[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.bool)(unsafe.Pointer(&newHigh[0])), (*C.bool)(unsafe.Pointer(&newLow[0])), (*C.bool)(unsafe.Pointer(&aboveMa[0])), (*C.bool)(unsafe.Pointer(&onBuySignal[0])), C.uintptr_t(len(change)), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(change)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(newHigh)
	runtime.KeepAlive(newLow)
	runtime.KeepAlive(aboveMa)
	runtime.KeepAlive(onBuySignal)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Trin) Reset() {
	C.wickra_trin_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Trin) Close() {
	if ind.handle != nil {
		C.wickra_trin_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TripleTopBottom wraps the TripleTopBottom indicator over the Wickra C ABI.
type TripleTopBottom struct {
	handle *C.struct_TripleTopBottom
}

// NewTripleTopBottom constructs a TripleTopBottom. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTripleTopBottom() (*TripleTopBottom, error) {
	ptr := C.wickra_triple_top_bottom_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TripleTopBottom{handle: ptr}
	runtime.SetFinalizer(obj, (*TripleTopBottom).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TripleTopBottom) WarmupPeriod() int {
	r := int(C.wickra_triple_top_bottom_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TripleTopBottom) IsReady() bool {
	r := bool(C.wickra_triple_top_bottom_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TripleTopBottom) Name() string {
	r := C.GoString(C.wickra_triple_top_bottom_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TripleTopBottom) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_triple_top_bottom_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TripleTopBottom) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_triple_top_bottom_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TripleTopBottom) Reset() {
	C.wickra_triple_top_bottom_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TripleTopBottom) Close() {
	if ind.handle != nil {
		C.wickra_triple_top_bottom_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Tristar wraps the Tristar indicator over the Wickra C ABI.
type Tristar struct {
	handle *C.struct_Tristar
}

// NewTristar constructs a Tristar. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTristar() (*Tristar, error) {
	ptr := C.wickra_tristar_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Tristar{handle: ptr}
	runtime.SetFinalizer(obj, (*Tristar).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Tristar) WarmupPeriod() int {
	r := int(C.wickra_tristar_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Tristar) IsReady() bool {
	r := bool(C.wickra_tristar_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Tristar) Name() string {
	r := C.GoString(C.wickra_tristar_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Tristar) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_tristar_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Tristar) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_tristar_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Tristar) Reset() {
	C.wickra_tristar_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Tristar) Close() {
	if ind.handle != nil {
		C.wickra_tristar_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Trix wraps the Trix indicator over the Wickra C ABI.
type Trix struct {
	handle *C.struct_Trix
}

// NewTrix constructs a Trix. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTrix(period int) (*Trix, error) {
	ptr := C.wickra_trix_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Trix{handle: ptr}
	runtime.SetFinalizer(obj, (*Trix).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Trix) WarmupPeriod() int {
	r := int(C.wickra_trix_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Trix) IsReady() bool {
	r := bool(C.wickra_trix_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Trix) Name() string {
	r := C.GoString(C.wickra_trix_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Trix) Update(value float64) float64 {
	r := float64(C.wickra_trix_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Trix) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_trix_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Trix) Reset() {
	C.wickra_trix_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Trix) Close() {
	if ind.handle != nil {
		C.wickra_trix_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TrueRange wraps the TrueRange indicator over the Wickra C ABI.
type TrueRange struct {
	handle *C.struct_TrueRange
}

// NewTrueRange constructs a TrueRange. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTrueRange() (*TrueRange, error) {
	ptr := C.wickra_true_range_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TrueRange{handle: ptr}
	runtime.SetFinalizer(obj, (*TrueRange).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TrueRange) WarmupPeriod() int {
	r := int(C.wickra_true_range_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TrueRange) IsReady() bool {
	r := bool(C.wickra_true_range_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TrueRange) Name() string {
	r := C.GoString(C.wickra_true_range_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TrueRange) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_true_range_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TrueRange) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_true_range_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TrueRange) Reset() {
	C.wickra_true_range_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TrueRange) Close() {
	if ind.handle != nil {
		C.wickra_true_range_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Tsf wraps the Tsf indicator over the Wickra C ABI.
type Tsf struct {
	handle *C.struct_Tsf
}

// NewTsf constructs a Tsf. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTsf(period int) (*Tsf, error) {
	ptr := C.wickra_tsf_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Tsf{handle: ptr}
	runtime.SetFinalizer(obj, (*Tsf).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Tsf) WarmupPeriod() int {
	r := int(C.wickra_tsf_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Tsf) IsReady() bool {
	r := bool(C.wickra_tsf_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Tsf) Name() string {
	r := C.GoString(C.wickra_tsf_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Tsf) Update(value float64) float64 {
	r := float64(C.wickra_tsf_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Tsf) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_tsf_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Tsf) Reset() {
	C.wickra_tsf_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Tsf) Close() {
	if ind.handle != nil {
		C.wickra_tsf_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TsfOscillator wraps the TsfOscillator indicator over the Wickra C ABI.
type TsfOscillator struct {
	handle *C.struct_TsfOscillator
}

// NewTsfOscillator constructs a TsfOscillator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTsfOscillator(period int) (*TsfOscillator, error) {
	ptr := C.wickra_tsf_oscillator_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TsfOscillator{handle: ptr}
	runtime.SetFinalizer(obj, (*TsfOscillator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TsfOscillator) WarmupPeriod() int {
	r := int(C.wickra_tsf_oscillator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TsfOscillator) IsReady() bool {
	r := bool(C.wickra_tsf_oscillator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TsfOscillator) Name() string {
	r := C.GoString(C.wickra_tsf_oscillator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TsfOscillator) Update(value float64) float64 {
	r := float64(C.wickra_tsf_oscillator_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TsfOscillator) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_tsf_oscillator_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TsfOscillator) Reset() {
	C.wickra_tsf_oscillator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TsfOscillator) Close() {
	if ind.handle != nil {
		C.wickra_tsf_oscillator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Tsi wraps the Tsi indicator over the Wickra C ABI.
type Tsi struct {
	handle *C.struct_Tsi
}

// NewTsi constructs a Tsi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTsi(long int, short int) (*Tsi, error) {
	ptr := C.wickra_tsi_new(C.uintptr_t(long), C.uintptr_t(short))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Tsi{handle: ptr}
	runtime.SetFinalizer(obj, (*Tsi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Tsi) WarmupPeriod() int {
	r := int(C.wickra_tsi_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Tsi) IsReady() bool {
	r := bool(C.wickra_tsi_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Tsi) Name() string {
	r := C.GoString(C.wickra_tsi_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Tsi) Update(value float64) float64 {
	r := float64(C.wickra_tsi_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Tsi) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_tsi_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Tsi) Reset() {
	C.wickra_tsi_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Tsi) Close() {
	if ind.handle != nil {
		C.wickra_tsi_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Tsv wraps the Tsv indicator over the Wickra C ABI.
type Tsv struct {
	handle *C.struct_Tsv
}

// NewTsv constructs a Tsv. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTsv(period int) (*Tsv, error) {
	ptr := C.wickra_tsv_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Tsv{handle: ptr}
	runtime.SetFinalizer(obj, (*Tsv).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Tsv) WarmupPeriod() int {
	r := int(C.wickra_tsv_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Tsv) IsReady() bool {
	r := bool(C.wickra_tsv_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Tsv) Name() string {
	r := C.GoString(C.wickra_tsv_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Tsv) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_tsv_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Tsv) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_tsv_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Tsv) Reset() {
	C.wickra_tsv_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Tsv) Close() {
	if ind.handle != nil {
		C.wickra_tsv_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TtmSqueeze wraps the TtmSqueeze indicator over the Wickra C ABI.
type TtmSqueeze struct {
	handle *C.struct_TtmSqueeze
}

// NewTtmSqueeze constructs a TtmSqueeze. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTtmSqueeze(period int, bbMult float64, kcMult float64) (*TtmSqueeze, error) {
	ptr := C.wickra_ttm_squeeze_new(C.uintptr_t(period), C.double(bbMult), C.double(kcMult))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TtmSqueeze{handle: ptr}
	runtime.SetFinalizer(obj, (*TtmSqueeze).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TtmSqueeze) WarmupPeriod() int {
	r := int(C.wickra_ttm_squeeze_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TtmSqueeze) IsReady() bool {
	r := bool(C.wickra_ttm_squeeze_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TtmSqueeze) Name() string {
	r := C.GoString(C.wickra_ttm_squeeze_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *TtmSqueeze) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (TtmSqueezeOutput, bool) {
	var out C.struct_WickraTtmSqueezeOutput
	ok := bool(C.wickra_ttm_squeeze_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return TtmSqueezeOutput{}, false
	}
	return TtmSqueezeOutput{float64(out.squeeze), float64(out.momentum)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TtmSqueeze) Reset() {
	C.wickra_ttm_squeeze_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TtmSqueeze) Close() {
	if ind.handle != nil {
		C.wickra_ttm_squeeze_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TtmTrend wraps the TtmTrend indicator over the Wickra C ABI.
type TtmTrend struct {
	handle *C.struct_TtmTrend
}

// NewTtmTrend constructs a TtmTrend. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTtmTrend(period int) (*TtmTrend, error) {
	ptr := C.wickra_ttm_trend_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TtmTrend{handle: ptr}
	runtime.SetFinalizer(obj, (*TtmTrend).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TtmTrend) WarmupPeriod() int {
	r := int(C.wickra_ttm_trend_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TtmTrend) IsReady() bool {
	r := bool(C.wickra_ttm_trend_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TtmTrend) Name() string {
	r := C.GoString(C.wickra_ttm_trend_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TtmTrend) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_ttm_trend_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TtmTrend) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_ttm_trend_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TtmTrend) Reset() {
	C.wickra_ttm_trend_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TtmTrend) Close() {
	if ind.handle != nil {
		C.wickra_ttm_trend_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TurnOfMonth wraps the TurnOfMonth indicator over the Wickra C ABI.
type TurnOfMonth struct {
	handle *C.struct_TurnOfMonth
}

// NewTurnOfMonth constructs a TurnOfMonth. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTurnOfMonth(nFirst uint32, nLast uint32, utcOffsetMinutes int32) (*TurnOfMonth, error) {
	ptr := C.wickra_turn_of_month_new(C.uint32_t(nFirst), C.uint32_t(nLast), C.int32_t(utcOffsetMinutes))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TurnOfMonth{handle: ptr}
	runtime.SetFinalizer(obj, (*TurnOfMonth).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TurnOfMonth) WarmupPeriod() int {
	r := int(C.wickra_turn_of_month_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TurnOfMonth) IsReady() bool {
	r := bool(C.wickra_turn_of_month_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TurnOfMonth) Name() string {
	r := C.GoString(C.wickra_turn_of_month_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TurnOfMonth) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_turn_of_month_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TurnOfMonth) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_turn_of_month_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TurnOfMonth) Reset() {
	C.wickra_turn_of_month_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TurnOfMonth) Close() {
	if ind.handle != nil {
		C.wickra_turn_of_month_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Tweezer wraps the Tweezer indicator over the Wickra C ABI.
type Tweezer struct {
	handle *C.struct_Tweezer
}

// NewTweezer constructs a Tweezer. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTweezer() (*Tweezer, error) {
	ptr := C.wickra_tweezer_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Tweezer{handle: ptr}
	runtime.SetFinalizer(obj, (*Tweezer).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Tweezer) WarmupPeriod() int {
	r := int(C.wickra_tweezer_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Tweezer) IsReady() bool {
	r := bool(C.wickra_tweezer_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Tweezer) Name() string {
	r := C.GoString(C.wickra_tweezer_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Tweezer) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_tweezer_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Tweezer) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_tweezer_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Tweezer) Reset() {
	C.wickra_tweezer_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Tweezer) Close() {
	if ind.handle != nil {
		C.wickra_tweezer_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TwiggsMoneyFlow wraps the TwiggsMoneyFlow indicator over the Wickra C ABI.
type TwiggsMoneyFlow struct {
	handle *C.struct_TwiggsMoneyFlow
}

// NewTwiggsMoneyFlow constructs a TwiggsMoneyFlow. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTwiggsMoneyFlow(period int) (*TwiggsMoneyFlow, error) {
	ptr := C.wickra_twiggs_money_flow_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TwiggsMoneyFlow{handle: ptr}
	runtime.SetFinalizer(obj, (*TwiggsMoneyFlow).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TwiggsMoneyFlow) WarmupPeriod() int {
	r := int(C.wickra_twiggs_money_flow_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TwiggsMoneyFlow) IsReady() bool {
	r := bool(C.wickra_twiggs_money_flow_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TwiggsMoneyFlow) Name() string {
	r := C.GoString(C.wickra_twiggs_money_flow_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TwiggsMoneyFlow) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_twiggs_money_flow_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TwiggsMoneyFlow) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_twiggs_money_flow_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TwiggsMoneyFlow) Reset() {
	C.wickra_twiggs_money_flow_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TwiggsMoneyFlow) Close() {
	if ind.handle != nil {
		C.wickra_twiggs_money_flow_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TwoCrows wraps the TwoCrows indicator over the Wickra C ABI.
type TwoCrows struct {
	handle *C.struct_TwoCrows
}

// NewTwoCrows constructs a TwoCrows. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTwoCrows() (*TwoCrows, error) {
	ptr := C.wickra_two_crows_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TwoCrows{handle: ptr}
	runtime.SetFinalizer(obj, (*TwoCrows).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TwoCrows) WarmupPeriod() int {
	r := int(C.wickra_two_crows_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TwoCrows) IsReady() bool {
	r := bool(C.wickra_two_crows_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TwoCrows) Name() string {
	r := C.GoString(C.wickra_two_crows_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TwoCrows) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_two_crows_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TwoCrows) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_two_crows_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TwoCrows) Reset() {
	C.wickra_two_crows_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TwoCrows) Close() {
	if ind.handle != nil {
		C.wickra_two_crows_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// TypicalPrice wraps the TypicalPrice indicator over the Wickra C ABI.
type TypicalPrice struct {
	handle *C.struct_TypicalPrice
}

// NewTypicalPrice constructs a TypicalPrice. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewTypicalPrice() (*TypicalPrice, error) {
	ptr := C.wickra_typical_price_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &TypicalPrice{handle: ptr}
	runtime.SetFinalizer(obj, (*TypicalPrice).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *TypicalPrice) WarmupPeriod() int {
	r := int(C.wickra_typical_price_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *TypicalPrice) IsReady() bool {
	r := bool(C.wickra_typical_price_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *TypicalPrice) Name() string {
	r := C.GoString(C.wickra_typical_price_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *TypicalPrice) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_typical_price_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *TypicalPrice) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_typical_price_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *TypicalPrice) Reset() {
	C.wickra_typical_price_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *TypicalPrice) Close() {
	if ind.handle != nil {
		C.wickra_typical_price_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// UlcerIndex wraps the UlcerIndex indicator over the Wickra C ABI.
type UlcerIndex struct {
	handle *C.struct_UlcerIndex
}

// NewUlcerIndex constructs a UlcerIndex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewUlcerIndex(period int) (*UlcerIndex, error) {
	ptr := C.wickra_ulcer_index_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &UlcerIndex{handle: ptr}
	runtime.SetFinalizer(obj, (*UlcerIndex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *UlcerIndex) WarmupPeriod() int {
	r := int(C.wickra_ulcer_index_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *UlcerIndex) IsReady() bool {
	r := bool(C.wickra_ulcer_index_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *UlcerIndex) Name() string {
	r := C.GoString(C.wickra_ulcer_index_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *UlcerIndex) Update(value float64) float64 {
	r := float64(C.wickra_ulcer_index_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *UlcerIndex) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_ulcer_index_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *UlcerIndex) Reset() {
	C.wickra_ulcer_index_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *UlcerIndex) Close() {
	if ind.handle != nil {
		C.wickra_ulcer_index_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// UltimateOscillator wraps the UltimateOscillator indicator over the Wickra C ABI.
type UltimateOscillator struct {
	handle *C.struct_UltimateOscillator
}

// NewUltimateOscillator constructs a UltimateOscillator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewUltimateOscillator(short int, mid int, long int) (*UltimateOscillator, error) {
	ptr := C.wickra_ultimate_oscillator_new(C.uintptr_t(short), C.uintptr_t(mid), C.uintptr_t(long))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &UltimateOscillator{handle: ptr}
	runtime.SetFinalizer(obj, (*UltimateOscillator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *UltimateOscillator) WarmupPeriod() int {
	r := int(C.wickra_ultimate_oscillator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *UltimateOscillator) IsReady() bool {
	r := bool(C.wickra_ultimate_oscillator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *UltimateOscillator) Name() string {
	r := C.GoString(C.wickra_ultimate_oscillator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *UltimateOscillator) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_ultimate_oscillator_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *UltimateOscillator) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_ultimate_oscillator_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *UltimateOscillator) Reset() {
	C.wickra_ultimate_oscillator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *UltimateOscillator) Close() {
	if ind.handle != nil {
		C.wickra_ultimate_oscillator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// UniqueThreeRiver wraps the UniqueThreeRiver indicator over the Wickra C ABI.
type UniqueThreeRiver struct {
	handle *C.struct_UniqueThreeRiver
}

// NewUniqueThreeRiver constructs a UniqueThreeRiver. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewUniqueThreeRiver() (*UniqueThreeRiver, error) {
	ptr := C.wickra_unique_three_river_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &UniqueThreeRiver{handle: ptr}
	runtime.SetFinalizer(obj, (*UniqueThreeRiver).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *UniqueThreeRiver) WarmupPeriod() int {
	r := int(C.wickra_unique_three_river_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *UniqueThreeRiver) IsReady() bool {
	r := bool(C.wickra_unique_three_river_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *UniqueThreeRiver) Name() string {
	r := C.GoString(C.wickra_unique_three_river_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *UniqueThreeRiver) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_unique_three_river_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *UniqueThreeRiver) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_unique_three_river_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *UniqueThreeRiver) Reset() {
	C.wickra_unique_three_river_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *UniqueThreeRiver) Close() {
	if ind.handle != nil {
		C.wickra_unique_three_river_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// UniversalOscillator wraps the UniversalOscillator indicator over the Wickra C ABI.
type UniversalOscillator struct {
	handle *C.struct_UniversalOscillator
}

// NewUniversalOscillator constructs a UniversalOscillator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewUniversalOscillator(period int) (*UniversalOscillator, error) {
	ptr := C.wickra_universal_oscillator_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &UniversalOscillator{handle: ptr}
	runtime.SetFinalizer(obj, (*UniversalOscillator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *UniversalOscillator) WarmupPeriod() int {
	r := int(C.wickra_universal_oscillator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *UniversalOscillator) IsReady() bool {
	r := bool(C.wickra_universal_oscillator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *UniversalOscillator) Name() string {
	r := C.GoString(C.wickra_universal_oscillator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *UniversalOscillator) Update(value float64) float64 {
	r := float64(C.wickra_universal_oscillator_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *UniversalOscillator) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_universal_oscillator_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *UniversalOscillator) Reset() {
	C.wickra_universal_oscillator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *UniversalOscillator) Close() {
	if ind.handle != nil {
		C.wickra_universal_oscillator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// UpDownVolumeRatio wraps the UpDownVolumeRatio indicator over the Wickra C ABI.
type UpDownVolumeRatio struct {
	handle *C.struct_UpDownVolumeRatio
}

// NewUpDownVolumeRatio constructs a UpDownVolumeRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewUpDownVolumeRatio() (*UpDownVolumeRatio, error) {
	ptr := C.wickra_up_down_volume_ratio_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &UpDownVolumeRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*UpDownVolumeRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *UpDownVolumeRatio) WarmupPeriod() int {
	r := int(C.wickra_up_down_volume_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *UpDownVolumeRatio) IsReady() bool {
	r := bool(C.wickra_up_down_volume_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *UpDownVolumeRatio) Name() string {
	r := C.GoString(C.wickra_up_down_volume_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one cross-sectional snapshot and returns the indicator
// value (NaN until warmed up). Slices in a group must share a length.
func (ind *UpDownVolumeRatio) Update(change []float64, volume []float64, newHigh []bool, newLow []bool, aboveMa []bool, onBuySignal []bool, timestamp int64) float64 {
	if len(volume) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newHigh) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(newLow) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(aboveMa) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	if len(onBuySignal) != len(change) {
		panic("wickra: input slices in the same group must have equal length")
	}
	r := float64(C.wickra_up_down_volume_ratio_update(ind.handle, (*C.double)(unsafe.Pointer(&change[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.bool)(unsafe.Pointer(&newHigh[0])), (*C.bool)(unsafe.Pointer(&newLow[0])), (*C.bool)(unsafe.Pointer(&aboveMa[0])), (*C.bool)(unsafe.Pointer(&onBuySignal[0])), C.uintptr_t(len(change)), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(change)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(newHigh)
	runtime.KeepAlive(newLow)
	runtime.KeepAlive(aboveMa)
	runtime.KeepAlive(onBuySignal)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *UpDownVolumeRatio) Reset() {
	C.wickra_up_down_volume_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *UpDownVolumeRatio) Close() {
	if ind.handle != nil {
		C.wickra_up_down_volume_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// UpsideGapThreeMethods wraps the UpsideGapThreeMethods indicator over the Wickra C ABI.
type UpsideGapThreeMethods struct {
	handle *C.struct_UpsideGapThreeMethods
}

// NewUpsideGapThreeMethods constructs a UpsideGapThreeMethods. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewUpsideGapThreeMethods() (*UpsideGapThreeMethods, error) {
	ptr := C.wickra_upside_gap_three_methods_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &UpsideGapThreeMethods{handle: ptr}
	runtime.SetFinalizer(obj, (*UpsideGapThreeMethods).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *UpsideGapThreeMethods) WarmupPeriod() int {
	r := int(C.wickra_upside_gap_three_methods_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *UpsideGapThreeMethods) IsReady() bool {
	r := bool(C.wickra_upside_gap_three_methods_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *UpsideGapThreeMethods) Name() string {
	r := C.GoString(C.wickra_upside_gap_three_methods_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *UpsideGapThreeMethods) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_upside_gap_three_methods_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *UpsideGapThreeMethods) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_upside_gap_three_methods_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *UpsideGapThreeMethods) Reset() {
	C.wickra_upside_gap_three_methods_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *UpsideGapThreeMethods) Close() {
	if ind.handle != nil {
		C.wickra_upside_gap_three_methods_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// UpsideGapTwoCrows wraps the UpsideGapTwoCrows indicator over the Wickra C ABI.
type UpsideGapTwoCrows struct {
	handle *C.struct_UpsideGapTwoCrows
}

// NewUpsideGapTwoCrows constructs a UpsideGapTwoCrows. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewUpsideGapTwoCrows() (*UpsideGapTwoCrows, error) {
	ptr := C.wickra_upside_gap_two_crows_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &UpsideGapTwoCrows{handle: ptr}
	runtime.SetFinalizer(obj, (*UpsideGapTwoCrows).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *UpsideGapTwoCrows) WarmupPeriod() int {
	r := int(C.wickra_upside_gap_two_crows_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *UpsideGapTwoCrows) IsReady() bool {
	r := bool(C.wickra_upside_gap_two_crows_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *UpsideGapTwoCrows) Name() string {
	r := C.GoString(C.wickra_upside_gap_two_crows_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *UpsideGapTwoCrows) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_upside_gap_two_crows_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *UpsideGapTwoCrows) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_upside_gap_two_crows_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *UpsideGapTwoCrows) Reset() {
	C.wickra_upside_gap_two_crows_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *UpsideGapTwoCrows) Close() {
	if ind.handle != nil {
		C.wickra_upside_gap_two_crows_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// UpsidePotentialRatio wraps the UpsidePotentialRatio indicator over the Wickra C ABI.
type UpsidePotentialRatio struct {
	handle *C.struct_UpsidePotentialRatio
}

// NewUpsidePotentialRatio constructs a UpsidePotentialRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewUpsidePotentialRatio(period int, mar float64) (*UpsidePotentialRatio, error) {
	ptr := C.wickra_upside_potential_ratio_new(C.uintptr_t(period), C.double(mar))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &UpsidePotentialRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*UpsidePotentialRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *UpsidePotentialRatio) WarmupPeriod() int {
	r := int(C.wickra_upside_potential_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *UpsidePotentialRatio) IsReady() bool {
	r := bool(C.wickra_upside_potential_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *UpsidePotentialRatio) Name() string {
	r := C.GoString(C.wickra_upside_potential_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *UpsidePotentialRatio) Update(value float64) float64 {
	r := float64(C.wickra_upside_potential_ratio_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *UpsidePotentialRatio) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_upside_potential_ratio_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *UpsidePotentialRatio) Reset() {
	C.wickra_upside_potential_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *UpsidePotentialRatio) Close() {
	if ind.handle != nil {
		C.wickra_upside_potential_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ValueArea wraps the ValueArea indicator over the Wickra C ABI.
type ValueArea struct {
	handle *C.struct_ValueArea
}

// NewValueArea constructs a ValueArea. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewValueArea(period int, binCount int, valueAreaPct float64) (*ValueArea, error) {
	ptr := C.wickra_value_area_new(C.uintptr_t(period), C.uintptr_t(binCount), C.double(valueAreaPct))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ValueArea{handle: ptr}
	runtime.SetFinalizer(obj, (*ValueArea).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ValueArea) WarmupPeriod() int {
	r := int(C.wickra_value_area_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ValueArea) IsReady() bool {
	r := bool(C.wickra_value_area_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ValueArea) Name() string {
	r := C.GoString(C.wickra_value_area_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *ValueArea) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (ValueAreaOutput, bool) {
	var out C.struct_WickraValueAreaOutput
	ok := bool(C.wickra_value_area_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return ValueAreaOutput{}, false
	}
	return ValueAreaOutput{float64(out.poc), float64(out.vah), float64(out.val)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ValueArea) Reset() {
	C.wickra_value_area_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ValueArea) Close() {
	if ind.handle != nil {
		C.wickra_value_area_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ValueAtRisk wraps the ValueAtRisk indicator over the Wickra C ABI.
type ValueAtRisk struct {
	handle *C.struct_ValueAtRisk
}

// NewValueAtRisk constructs a ValueAtRisk. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewValueAtRisk(period int, confidence float64) (*ValueAtRisk, error) {
	ptr := C.wickra_value_at_risk_new(C.uintptr_t(period), C.double(confidence))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ValueAtRisk{handle: ptr}
	runtime.SetFinalizer(obj, (*ValueAtRisk).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ValueAtRisk) WarmupPeriod() int {
	r := int(C.wickra_value_at_risk_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ValueAtRisk) IsReady() bool {
	r := bool(C.wickra_value_at_risk_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ValueAtRisk) Name() string {
	r := C.GoString(C.wickra_value_at_risk_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ValueAtRisk) Update(value float64) float64 {
	r := float64(C.wickra_value_at_risk_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ValueAtRisk) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_value_at_risk_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ValueAtRisk) Reset() {
	C.wickra_value_at_risk_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ValueAtRisk) Close() {
	if ind.handle != nil {
		C.wickra_value_at_risk_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Variance wraps the Variance indicator over the Wickra C ABI.
type Variance struct {
	handle *C.struct_Variance
}

// NewVariance constructs a Variance. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVariance(period int) (*Variance, error) {
	ptr := C.wickra_variance_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Variance{handle: ptr}
	runtime.SetFinalizer(obj, (*Variance).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Variance) WarmupPeriod() int {
	r := int(C.wickra_variance_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Variance) IsReady() bool {
	r := bool(C.wickra_variance_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Variance) Name() string {
	r := C.GoString(C.wickra_variance_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Variance) Update(value float64) float64 {
	r := float64(C.wickra_variance_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Variance) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_variance_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Variance) Reset() {
	C.wickra_variance_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Variance) Close() {
	if ind.handle != nil {
		C.wickra_variance_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// VarianceRatio wraps the VarianceRatio indicator over the Wickra C ABI.
type VarianceRatio struct {
	handle *C.struct_VarianceRatio
}

// NewVarianceRatio constructs a VarianceRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVarianceRatio(period int, q int) (*VarianceRatio, error) {
	ptr := C.wickra_variance_ratio_new(C.uintptr_t(period), C.uintptr_t(q))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &VarianceRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*VarianceRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *VarianceRatio) WarmupPeriod() int {
	r := int(C.wickra_variance_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *VarianceRatio) IsReady() bool {
	r := bool(C.wickra_variance_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *VarianceRatio) Name() string {
	r := C.GoString(C.wickra_variance_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *VarianceRatio) Update(x float64, y float64) float64 {
	r := float64(C.wickra_variance_ratio_update(ind.handle, C.double(x), C.double(y)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *VarianceRatio) Batch(x []float64, y []float64) []float64 {
	n := len(x)
	if len(y) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_variance_ratio_batch(ind.handle, (*C.double)(unsafe.Pointer(&x[0])), (*C.double)(unsafe.Pointer(&y[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(x)
	runtime.KeepAlive(y)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *VarianceRatio) Reset() {
	C.wickra_variance_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *VarianceRatio) Close() {
	if ind.handle != nil {
		C.wickra_variance_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// VerticalHorizontalFilter wraps the VerticalHorizontalFilter indicator over the Wickra C ABI.
type VerticalHorizontalFilter struct {
	handle *C.struct_VerticalHorizontalFilter
}

// NewVerticalHorizontalFilter constructs a VerticalHorizontalFilter. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVerticalHorizontalFilter(period int) (*VerticalHorizontalFilter, error) {
	ptr := C.wickra_vertical_horizontal_filter_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &VerticalHorizontalFilter{handle: ptr}
	runtime.SetFinalizer(obj, (*VerticalHorizontalFilter).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *VerticalHorizontalFilter) WarmupPeriod() int {
	r := int(C.wickra_vertical_horizontal_filter_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *VerticalHorizontalFilter) IsReady() bool {
	r := bool(C.wickra_vertical_horizontal_filter_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *VerticalHorizontalFilter) Name() string {
	r := C.GoString(C.wickra_vertical_horizontal_filter_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *VerticalHorizontalFilter) Update(value float64) float64 {
	r := float64(C.wickra_vertical_horizontal_filter_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *VerticalHorizontalFilter) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_vertical_horizontal_filter_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *VerticalHorizontalFilter) Reset() {
	C.wickra_vertical_horizontal_filter_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *VerticalHorizontalFilter) Close() {
	if ind.handle != nil {
		C.wickra_vertical_horizontal_filter_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Vidya wraps the Vidya indicator over the Wickra C ABI.
type Vidya struct {
	handle *C.struct_Vidya
}

// NewVidya constructs a Vidya. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVidya(period int, cmoPeriod int) (*Vidya, error) {
	ptr := C.wickra_vidya_new(C.uintptr_t(period), C.uintptr_t(cmoPeriod))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Vidya{handle: ptr}
	runtime.SetFinalizer(obj, (*Vidya).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Vidya) WarmupPeriod() int {
	r := int(C.wickra_vidya_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Vidya) IsReady() bool {
	r := bool(C.wickra_vidya_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Vidya) Name() string {
	r := C.GoString(C.wickra_vidya_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Vidya) Update(value float64) float64 {
	r := float64(C.wickra_vidya_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Vidya) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_vidya_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Vidya) Reset() {
	C.wickra_vidya_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Vidya) Close() {
	if ind.handle != nil {
		C.wickra_vidya_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// VolatilityCone wraps the VolatilityCone indicator over the Wickra C ABI.
type VolatilityCone struct {
	handle *C.struct_VolatilityCone
}

// NewVolatilityCone constructs a VolatilityCone. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVolatilityCone(window int, lookback int) (*VolatilityCone, error) {
	ptr := C.wickra_volatility_cone_new(C.uintptr_t(window), C.uintptr_t(lookback))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &VolatilityCone{handle: ptr}
	runtime.SetFinalizer(obj, (*VolatilityCone).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *VolatilityCone) WarmupPeriod() int {
	r := int(C.wickra_volatility_cone_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *VolatilityCone) IsReady() bool {
	r := bool(C.wickra_volatility_cone_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *VolatilityCone) Name() string {
	r := C.GoString(C.wickra_volatility_cone_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *VolatilityCone) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (VolatilityConeOutput, bool) {
	var out C.struct_WickraVolatilityConeOutput
	ok := bool(C.wickra_volatility_cone_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return VolatilityConeOutput{}, false
	}
	return VolatilityConeOutput{float64(out.current), float64(out.min), float64(out.median), float64(out.max), float64(out.percentile)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *VolatilityCone) Reset() {
	C.wickra_volatility_cone_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *VolatilityCone) Close() {
	if ind.handle != nil {
		C.wickra_volatility_cone_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// VolatilityOfVolatility wraps the VolatilityOfVolatility indicator over the Wickra C ABI.
type VolatilityOfVolatility struct {
	handle *C.struct_VolatilityOfVolatility
}

// NewVolatilityOfVolatility constructs a VolatilityOfVolatility. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVolatilityOfVolatility(volWindow int, vovWindow int) (*VolatilityOfVolatility, error) {
	ptr := C.wickra_volatility_of_volatility_new(C.uintptr_t(volWindow), C.uintptr_t(vovWindow))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &VolatilityOfVolatility{handle: ptr}
	runtime.SetFinalizer(obj, (*VolatilityOfVolatility).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *VolatilityOfVolatility) WarmupPeriod() int {
	r := int(C.wickra_volatility_of_volatility_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *VolatilityOfVolatility) IsReady() bool {
	r := bool(C.wickra_volatility_of_volatility_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *VolatilityOfVolatility) Name() string {
	r := C.GoString(C.wickra_volatility_of_volatility_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *VolatilityOfVolatility) Update(value float64) float64 {
	r := float64(C.wickra_volatility_of_volatility_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *VolatilityOfVolatility) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_volatility_of_volatility_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *VolatilityOfVolatility) Reset() {
	C.wickra_volatility_of_volatility_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *VolatilityOfVolatility) Close() {
	if ind.handle != nil {
		C.wickra_volatility_of_volatility_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// VolatilityRatio wraps the VolatilityRatio indicator over the Wickra C ABI.
type VolatilityRatio struct {
	handle *C.struct_VolatilityRatio
}

// NewVolatilityRatio constructs a VolatilityRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVolatilityRatio(period int) (*VolatilityRatio, error) {
	ptr := C.wickra_volatility_ratio_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &VolatilityRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*VolatilityRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *VolatilityRatio) WarmupPeriod() int {
	r := int(C.wickra_volatility_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *VolatilityRatio) IsReady() bool {
	r := bool(C.wickra_volatility_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *VolatilityRatio) Name() string {
	r := C.GoString(C.wickra_volatility_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *VolatilityRatio) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_volatility_ratio_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *VolatilityRatio) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_volatility_ratio_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *VolatilityRatio) Reset() {
	C.wickra_volatility_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *VolatilityRatio) Close() {
	if ind.handle != nil {
		C.wickra_volatility_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// VoltyStop wraps the VoltyStop indicator over the Wickra C ABI.
type VoltyStop struct {
	handle *C.struct_VoltyStop
}

// NewVoltyStop constructs a VoltyStop. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVoltyStop(atrPeriod int, multiplier float64) (*VoltyStop, error) {
	ptr := C.wickra_volty_stop_new(C.uintptr_t(atrPeriod), C.double(multiplier))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &VoltyStop{handle: ptr}
	runtime.SetFinalizer(obj, (*VoltyStop).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *VoltyStop) WarmupPeriod() int {
	r := int(C.wickra_volty_stop_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *VoltyStop) IsReady() bool {
	r := bool(C.wickra_volty_stop_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *VoltyStop) Name() string {
	r := C.GoString(C.wickra_volty_stop_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *VoltyStop) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_volty_stop_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *VoltyStop) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_volty_stop_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *VoltyStop) Reset() {
	C.wickra_volty_stop_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *VoltyStop) Close() {
	if ind.handle != nil {
		C.wickra_volty_stop_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// VolumeBars wraps the VolumeBars indicator over the Wickra C ABI.
type VolumeBars struct {
	handle *C.struct_VolumeBars
}

// NewVolumeBars constructs a VolumeBars. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVolumeBars(volumePerBar float64) (*VolumeBars, error) {
	ptr := C.wickra_volume_bars_new(C.double(volumePerBar))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &VolumeBars{handle: ptr}
	runtime.SetFinalizer(obj, (*VolumeBars).Close)
	return obj, nil
}

// Name returns the indicator's canonical name.
func (ind *VolumeBars) Name() string {
	r := C.GoString(C.wickra_volume_bars_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one candle and returns any bars completed by it
// (a single candle may complete several).
func (ind *VolumeBars) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) []VolumeBar {
	const capacity = 64
	var buf [capacity]C.struct_WickraVolumeBar
	n := int(C.wickra_volume_bars_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &buf[0], C.uintptr_t(capacity)))
	runtime.KeepAlive(ind)
	if n <= 0 {
		return nil
	}
	out := make([]VolumeBar, n)
	for i := 0; i < n; i++ {
		out[i] = VolumeBar{float64(buf[i].open), float64(buf[i].high), float64(buf[i].low), float64(buf[i].close), float64(buf[i].volume)}
	}
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *VolumeBars) Reset() {
	C.wickra_volume_bars_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *VolumeBars) Close() {
	if ind.handle != nil {
		C.wickra_volume_bars_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// VolumeByTimeProfile wraps the VolumeByTimeProfile indicator over the Wickra C ABI.
type VolumeByTimeProfile struct {
	handle    *C.struct_VolumeByTimeProfile
	valuesCap int
}

// NewVolumeByTimeProfile constructs a VolumeByTimeProfile. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVolumeByTimeProfile(buckets int, utcOffsetMinutes int32) (*VolumeByTimeProfile, error) {
	ptr := C.wickra_volume_by_time_profile_new(C.uintptr_t(buckets), C.int32_t(utcOffsetMinutes))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &VolumeByTimeProfile{handle: ptr}
	obj.valuesCap = buckets
	runtime.SetFinalizer(obj, (*VolumeByTimeProfile).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *VolumeByTimeProfile) WarmupPeriod() int {
	r := int(C.wickra_volume_by_time_profile_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *VolumeByTimeProfile) IsReady() bool {
	r := bool(C.wickra_volume_by_time_profile_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *VolumeByTimeProfile) Name() string {
	r := C.GoString(C.wickra_volume_by_time_profile_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the profile values
// (ok is false during warmup).
func (ind *VolumeByTimeProfile) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) ([]float64, bool) {
	values := make([]float64, ind.valuesCap)
	n := int(C.wickra_volume_by_time_profile_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), (*C.double)(unsafe.Pointer(&values[0])), C.uintptr_t(len(values))))
	runtime.KeepAlive(ind)
	if n < 0 {
		return nil, false
	}
	return values[:n], true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *VolumeByTimeProfile) Reset() {
	C.wickra_volume_by_time_profile_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *VolumeByTimeProfile) Close() {
	if ind.handle != nil {
		C.wickra_volume_by_time_profile_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// VolumeOscillator wraps the VolumeOscillator indicator over the Wickra C ABI.
type VolumeOscillator struct {
	handle *C.struct_VolumeOscillator
}

// NewVolumeOscillator constructs a VolumeOscillator. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVolumeOscillator(fast int, slow int) (*VolumeOscillator, error) {
	ptr := C.wickra_volume_oscillator_new(C.uintptr_t(fast), C.uintptr_t(slow))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &VolumeOscillator{handle: ptr}
	runtime.SetFinalizer(obj, (*VolumeOscillator).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *VolumeOscillator) WarmupPeriod() int {
	r := int(C.wickra_volume_oscillator_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *VolumeOscillator) IsReady() bool {
	r := bool(C.wickra_volume_oscillator_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *VolumeOscillator) Name() string {
	r := C.GoString(C.wickra_volume_oscillator_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *VolumeOscillator) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_volume_oscillator_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *VolumeOscillator) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_volume_oscillator_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *VolumeOscillator) Reset() {
	C.wickra_volume_oscillator_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *VolumeOscillator) Close() {
	if ind.handle != nil {
		C.wickra_volume_oscillator_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// VolumePriceTrend wraps the VolumePriceTrend indicator over the Wickra C ABI.
type VolumePriceTrend struct {
	handle *C.struct_VolumePriceTrend
}

// NewVolumePriceTrend constructs a VolumePriceTrend. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVolumePriceTrend() (*VolumePriceTrend, error) {
	ptr := C.wickra_volume_price_trend_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &VolumePriceTrend{handle: ptr}
	runtime.SetFinalizer(obj, (*VolumePriceTrend).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *VolumePriceTrend) WarmupPeriod() int {
	r := int(C.wickra_volume_price_trend_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *VolumePriceTrend) IsReady() bool {
	r := bool(C.wickra_volume_price_trend_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *VolumePriceTrend) Name() string {
	r := C.GoString(C.wickra_volume_price_trend_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *VolumePriceTrend) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_volume_price_trend_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *VolumePriceTrend) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_volume_price_trend_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *VolumePriceTrend) Reset() {
	C.wickra_volume_price_trend_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *VolumePriceTrend) Close() {
	if ind.handle != nil {
		C.wickra_volume_price_trend_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// VolumeProfile wraps the VolumeProfile indicator over the Wickra C ABI.
type VolumeProfile struct {
	handle    *C.struct_VolumeProfile
	valuesCap int
}

// NewVolumeProfile constructs a VolumeProfile. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVolumeProfile(period int, binCount int) (*VolumeProfile, error) {
	ptr := C.wickra_volume_profile_new(C.uintptr_t(period), C.uintptr_t(binCount))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &VolumeProfile{handle: ptr}
	obj.valuesCap = binCount
	runtime.SetFinalizer(obj, (*VolumeProfile).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *VolumeProfile) WarmupPeriod() int {
	r := int(C.wickra_volume_profile_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *VolumeProfile) IsReady() bool {
	r := bool(C.wickra_volume_profile_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *VolumeProfile) Name() string {
	r := C.GoString(C.wickra_volume_profile_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the profile snapshot
// (ok is false during warmup).
func (ind *VolumeProfile) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (VolumeProfileOutputScalars, bool) {
	values := make([]float64, ind.valuesCap)
	var sc C.struct_WickraVolumeProfileOutputScalars
	n := int(C.wickra_volume_profile_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &sc, (*C.double)(unsafe.Pointer(&values[0])), C.uintptr_t(len(values))))
	runtime.KeepAlive(ind)
	if n < 0 {
		return VolumeProfileOutputScalars{}, false
	}
	return VolumeProfileOutputScalars{PriceLow: float64(sc.price_low), PriceHigh: float64(sc.price_high), Values: values[:n]}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *VolumeProfile) Reset() {
	C.wickra_volume_profile_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *VolumeProfile) Close() {
	if ind.handle != nil {
		C.wickra_volume_profile_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// VolumeRsi wraps the VolumeRsi indicator over the Wickra C ABI.
type VolumeRsi struct {
	handle *C.struct_VolumeRsi
}

// NewVolumeRsi constructs a VolumeRsi. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVolumeRsi(period int) (*VolumeRsi, error) {
	ptr := C.wickra_volume_rsi_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &VolumeRsi{handle: ptr}
	runtime.SetFinalizer(obj, (*VolumeRsi).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *VolumeRsi) WarmupPeriod() int {
	r := int(C.wickra_volume_rsi_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *VolumeRsi) IsReady() bool {
	r := bool(C.wickra_volume_rsi_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *VolumeRsi) Name() string {
	r := C.GoString(C.wickra_volume_rsi_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *VolumeRsi) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_volume_rsi_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *VolumeRsi) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_volume_rsi_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *VolumeRsi) Reset() {
	C.wickra_volume_rsi_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *VolumeRsi) Close() {
	if ind.handle != nil {
		C.wickra_volume_rsi_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// VolumeWeightedMacd wraps the VolumeWeightedMacd indicator over the Wickra C ABI.
type VolumeWeightedMacd struct {
	handle *C.struct_VolumeWeightedMacd
}

// NewVolumeWeightedMacd constructs a VolumeWeightedMacd. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVolumeWeightedMacd(fast int, slow int, signal int) (*VolumeWeightedMacd, error) {
	ptr := C.wickra_volume_weighted_macd_new(C.uintptr_t(fast), C.uintptr_t(slow), C.uintptr_t(signal))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &VolumeWeightedMacd{handle: ptr}
	runtime.SetFinalizer(obj, (*VolumeWeightedMacd).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *VolumeWeightedMacd) WarmupPeriod() int {
	r := int(C.wickra_volume_weighted_macd_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *VolumeWeightedMacd) IsReady() bool {
	r := bool(C.wickra_volume_weighted_macd_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *VolumeWeightedMacd) Name() string {
	r := C.GoString(C.wickra_volume_weighted_macd_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *VolumeWeightedMacd) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (VolumeWeightedMacdOutput, bool) {
	var out C.struct_WickraVolumeWeightedMacdOutput
	ok := bool(C.wickra_volume_weighted_macd_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return VolumeWeightedMacdOutput{}, false
	}
	return VolumeWeightedMacdOutput{float64(out.macd), float64(out.signal), float64(out.histogram)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *VolumeWeightedMacd) Reset() {
	C.wickra_volume_weighted_macd_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *VolumeWeightedMacd) Close() {
	if ind.handle != nil {
		C.wickra_volume_weighted_macd_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// VolumeWeightedSr wraps the VolumeWeightedSr indicator over the Wickra C ABI.
type VolumeWeightedSr struct {
	handle *C.struct_VolumeWeightedSr
}

// NewVolumeWeightedSr constructs a VolumeWeightedSr. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVolumeWeightedSr(period int) (*VolumeWeightedSr, error) {
	ptr := C.wickra_volume_weighted_sr_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &VolumeWeightedSr{handle: ptr}
	runtime.SetFinalizer(obj, (*VolumeWeightedSr).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *VolumeWeightedSr) WarmupPeriod() int {
	r := int(C.wickra_volume_weighted_sr_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *VolumeWeightedSr) IsReady() bool {
	r := bool(C.wickra_volume_weighted_sr_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *VolumeWeightedSr) Name() string {
	r := C.GoString(C.wickra_volume_weighted_sr_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *VolumeWeightedSr) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (VolumeWeightedSrOutput, bool) {
	var out C.struct_WickraVolumeWeightedSrOutput
	ok := bool(C.wickra_volume_weighted_sr_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return VolumeWeightedSrOutput{}, false
	}
	return VolumeWeightedSrOutput{float64(out.support), float64(out.resistance)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *VolumeWeightedSr) Reset() {
	C.wickra_volume_weighted_sr_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *VolumeWeightedSr) Close() {
	if ind.handle != nil {
		C.wickra_volume_weighted_sr_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Vortex wraps the Vortex indicator over the Wickra C ABI.
type Vortex struct {
	handle *C.struct_Vortex
}

// NewVortex constructs a Vortex. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVortex(period int) (*Vortex, error) {
	ptr := C.wickra_vortex_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Vortex{handle: ptr}
	runtime.SetFinalizer(obj, (*Vortex).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Vortex) WarmupPeriod() int {
	r := int(C.wickra_vortex_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Vortex) IsReady() bool {
	r := bool(C.wickra_vortex_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Vortex) Name() string {
	r := C.GoString(C.wickra_vortex_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *Vortex) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (VortexOutput, bool) {
	var out C.struct_WickraVortexOutput
	ok := bool(C.wickra_vortex_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return VortexOutput{}, false
	}
	return VortexOutput{float64(out.plus), float64(out.minus)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Vortex) Reset() {
	C.wickra_vortex_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Vortex) Close() {
	if ind.handle != nil {
		C.wickra_vortex_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Vpin wraps the Vpin indicator over the Wickra C ABI.
type Vpin struct {
	handle *C.struct_Vpin
}

// NewVpin constructs a Vpin. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVpin(bucketVolume float64, numBuckets int) (*Vpin, error) {
	ptr := C.wickra_vpin_new(C.double(bucketVolume), C.uintptr_t(numBuckets))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Vpin{handle: ptr}
	runtime.SetFinalizer(obj, (*Vpin).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Vpin) WarmupPeriod() int {
	r := int(C.wickra_vpin_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Vpin) IsReady() bool {
	r := bool(C.wickra_vpin_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Vpin) Name() string {
	r := C.GoString(C.wickra_vpin_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Vpin) Update(price float64, size float64, isBuy bool, timestamp int64) float64 {
	r := float64(C.wickra_vpin_update(ind.handle, C.double(price), C.double(size), C.bool(isBuy), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Vpin) Reset() {
	C.wickra_vpin_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Vpin) Close() {
	if ind.handle != nil {
		C.wickra_vpin_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Vwap wraps the Vwap indicator over the Wickra C ABI.
type Vwap struct {
	handle *C.struct_Vwap
}

// NewVwap constructs a Vwap. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVwap() (*Vwap, error) {
	ptr := C.wickra_vwap_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Vwap{handle: ptr}
	runtime.SetFinalizer(obj, (*Vwap).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Vwap) WarmupPeriod() int {
	r := int(C.wickra_vwap_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Vwap) IsReady() bool {
	r := bool(C.wickra_vwap_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Vwap) Name() string {
	r := C.GoString(C.wickra_vwap_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Vwap) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_vwap_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Vwap) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_vwap_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Vwap) Reset() {
	C.wickra_vwap_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Vwap) Close() {
	if ind.handle != nil {
		C.wickra_vwap_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// VwapStdDevBands wraps the VwapStdDevBands indicator over the Wickra C ABI.
type VwapStdDevBands struct {
	handle *C.struct_VwapStdDevBands
}

// NewVwapStdDevBands constructs a VwapStdDevBands. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVwapStdDevBands(multiplier float64) (*VwapStdDevBands, error) {
	ptr := C.wickra_vwap_std_dev_bands_new(C.double(multiplier))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &VwapStdDevBands{handle: ptr}
	runtime.SetFinalizer(obj, (*VwapStdDevBands).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *VwapStdDevBands) WarmupPeriod() int {
	r := int(C.wickra_vwap_std_dev_bands_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *VwapStdDevBands) IsReady() bool {
	r := bool(C.wickra_vwap_std_dev_bands_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *VwapStdDevBands) Name() string {
	r := C.GoString(C.wickra_vwap_std_dev_bands_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *VwapStdDevBands) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (VwapStdDevBandsOutput, bool) {
	var out C.struct_WickraVwapStdDevBandsOutput
	ok := bool(C.wickra_vwap_std_dev_bands_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return VwapStdDevBandsOutput{}, false
	}
	return VwapStdDevBandsOutput{float64(out.upper), float64(out.middle), float64(out.lower), float64(out.stddev)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *VwapStdDevBands) Reset() {
	C.wickra_vwap_std_dev_bands_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *VwapStdDevBands) Close() {
	if ind.handle != nil {
		C.wickra_vwap_std_dev_bands_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Vwma wraps the Vwma indicator over the Wickra C ABI.
type Vwma struct {
	handle *C.struct_Vwma
}

// NewVwma constructs a Vwma. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVwma(period int) (*Vwma, error) {
	ptr := C.wickra_vwma_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Vwma{handle: ptr}
	runtime.SetFinalizer(obj, (*Vwma).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Vwma) WarmupPeriod() int {
	r := int(C.wickra_vwma_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Vwma) IsReady() bool {
	r := bool(C.wickra_vwma_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Vwma) Name() string {
	r := C.GoString(C.wickra_vwma_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Vwma) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_vwma_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Vwma) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_vwma_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Vwma) Reset() {
	C.wickra_vwma_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Vwma) Close() {
	if ind.handle != nil {
		C.wickra_vwma_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Vzo wraps the Vzo indicator over the Wickra C ABI.
type Vzo struct {
	handle *C.struct_Vzo
}

// NewVzo constructs a Vzo. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewVzo(period int) (*Vzo, error) {
	ptr := C.wickra_vzo_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Vzo{handle: ptr}
	runtime.SetFinalizer(obj, (*Vzo).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Vzo) WarmupPeriod() int {
	r := int(C.wickra_vzo_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Vzo) IsReady() bool {
	r := bool(C.wickra_vzo_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Vzo) Name() string {
	r := C.GoString(C.wickra_vzo_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Vzo) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_vzo_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Vzo) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_vzo_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Vzo) Reset() {
	C.wickra_vzo_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Vzo) Close() {
	if ind.handle != nil {
		C.wickra_vzo_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Wad wraps the Wad indicator over the Wickra C ABI.
type Wad struct {
	handle *C.struct_Wad
}

// NewWad constructs a Wad. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewWad() (*Wad, error) {
	ptr := C.wickra_wad_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Wad{handle: ptr}
	runtime.SetFinalizer(obj, (*Wad).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Wad) WarmupPeriod() int {
	r := int(C.wickra_wad_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Wad) IsReady() bool {
	r := bool(C.wickra_wad_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Wad) Name() string {
	r := C.GoString(C.wickra_wad_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Wad) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_wad_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Wad) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_wad_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Wad) Reset() {
	C.wickra_wad_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Wad) Close() {
	if ind.handle != nil {
		C.wickra_wad_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// WavePm wraps the WavePm indicator over the Wickra C ABI.
type WavePm struct {
	handle *C.struct_WavePm
}

// NewWavePm constructs a WavePm. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewWavePm(length int, smoothing int) (*WavePm, error) {
	ptr := C.wickra_wave_pm_new(C.uintptr_t(length), C.uintptr_t(smoothing))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &WavePm{handle: ptr}
	runtime.SetFinalizer(obj, (*WavePm).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *WavePm) WarmupPeriod() int {
	r := int(C.wickra_wave_pm_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *WavePm) IsReady() bool {
	r := bool(C.wickra_wave_pm_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *WavePm) Name() string {
	r := C.GoString(C.wickra_wave_pm_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *WavePm) Update(value float64) float64 {
	r := float64(C.wickra_wave_pm_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *WavePm) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_wave_pm_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *WavePm) Reset() {
	C.wickra_wave_pm_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *WavePm) Close() {
	if ind.handle != nil {
		C.wickra_wave_pm_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// WaveTrend wraps the WaveTrend indicator over the Wickra C ABI.
type WaveTrend struct {
	handle *C.struct_WaveTrend
}

// NewWaveTrend constructs a WaveTrend. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewWaveTrend(channelPeriod int, averagePeriod int, signalPeriod int) (*WaveTrend, error) {
	ptr := C.wickra_wave_trend_new(C.uintptr_t(channelPeriod), C.uintptr_t(averagePeriod), C.uintptr_t(signalPeriod))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &WaveTrend{handle: ptr}
	runtime.SetFinalizer(obj, (*WaveTrend).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *WaveTrend) WarmupPeriod() int {
	r := int(C.wickra_wave_trend_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *WaveTrend) IsReady() bool {
	r := bool(C.wickra_wave_trend_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *WaveTrend) Name() string {
	r := C.GoString(C.wickra_wave_trend_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *WaveTrend) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (WaveTrendOutput, bool) {
	var out C.struct_WickraWaveTrendOutput
	ok := bool(C.wickra_wave_trend_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return WaveTrendOutput{}, false
	}
	return WaveTrendOutput{float64(out.wt1), float64(out.wt2)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *WaveTrend) Reset() {
	C.wickra_wave_trend_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *WaveTrend) Close() {
	if ind.handle != nil {
		C.wickra_wave_trend_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Wedge wraps the Wedge indicator over the Wickra C ABI.
type Wedge struct {
	handle *C.struct_Wedge
}

// NewWedge constructs a Wedge. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewWedge() (*Wedge, error) {
	ptr := C.wickra_wedge_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Wedge{handle: ptr}
	runtime.SetFinalizer(obj, (*Wedge).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Wedge) WarmupPeriod() int {
	r := int(C.wickra_wedge_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Wedge) IsReady() bool {
	r := bool(C.wickra_wedge_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Wedge) Name() string {
	r := C.GoString(C.wickra_wedge_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Wedge) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_wedge_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Wedge) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_wedge_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Wedge) Reset() {
	C.wickra_wedge_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Wedge) Close() {
	if ind.handle != nil {
		C.wickra_wedge_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// WeightedClose wraps the WeightedClose indicator over the Wickra C ABI.
type WeightedClose struct {
	handle *C.struct_WeightedClose
}

// NewWeightedClose constructs a WeightedClose. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewWeightedClose() (*WeightedClose, error) {
	ptr := C.wickra_weighted_close_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &WeightedClose{handle: ptr}
	runtime.SetFinalizer(obj, (*WeightedClose).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *WeightedClose) WarmupPeriod() int {
	r := int(C.wickra_weighted_close_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *WeightedClose) IsReady() bool {
	r := bool(C.wickra_weighted_close_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *WeightedClose) Name() string {
	r := C.GoString(C.wickra_weighted_close_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *WeightedClose) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_weighted_close_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *WeightedClose) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_weighted_close_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *WeightedClose) Reset() {
	C.wickra_weighted_close_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *WeightedClose) Close() {
	if ind.handle != nil {
		C.wickra_weighted_close_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// WickRatio wraps the WickRatio indicator over the Wickra C ABI.
type WickRatio struct {
	handle *C.struct_WickRatio
}

// NewWickRatio constructs a WickRatio. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewWickRatio() (*WickRatio, error) {
	ptr := C.wickra_wick_ratio_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &WickRatio{handle: ptr}
	runtime.SetFinalizer(obj, (*WickRatio).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *WickRatio) WarmupPeriod() int {
	r := int(C.wickra_wick_ratio_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *WickRatio) IsReady() bool {
	r := bool(C.wickra_wick_ratio_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *WickRatio) Name() string {
	r := C.GoString(C.wickra_wick_ratio_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *WickRatio) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_wick_ratio_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *WickRatio) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_wick_ratio_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *WickRatio) Reset() {
	C.wickra_wick_ratio_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *WickRatio) Close() {
	if ind.handle != nil {
		C.wickra_wick_ratio_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// WilliamsFractals wraps the WilliamsFractals indicator over the Wickra C ABI.
type WilliamsFractals struct {
	handle *C.struct_WilliamsFractals
}

// NewWilliamsFractals constructs a WilliamsFractals. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewWilliamsFractals() (*WilliamsFractals, error) {
	ptr := C.wickra_williams_fractals_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &WilliamsFractals{handle: ptr}
	runtime.SetFinalizer(obj, (*WilliamsFractals).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *WilliamsFractals) WarmupPeriod() int {
	r := int(C.wickra_williams_fractals_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *WilliamsFractals) IsReady() bool {
	r := bool(C.wickra_williams_fractals_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *WilliamsFractals) Name() string {
	r := C.GoString(C.wickra_williams_fractals_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *WilliamsFractals) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (WilliamsFractalsOutput, bool) {
	var out C.struct_WickraWilliamsFractalsOutput
	ok := bool(C.wickra_williams_fractals_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return WilliamsFractalsOutput{}, false
	}
	return WilliamsFractalsOutput{float64(out.up), float64(out.down)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *WilliamsFractals) Reset() {
	C.wickra_williams_fractals_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *WilliamsFractals) Close() {
	if ind.handle != nil {
		C.wickra_williams_fractals_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// WilliamsR wraps the WilliamsR indicator over the Wickra C ABI.
type WilliamsR struct {
	handle *C.struct_WilliamsR
}

// NewWilliamsR constructs a WilliamsR. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewWilliamsR(period int) (*WilliamsR, error) {
	ptr := C.wickra_williams_r_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &WilliamsR{handle: ptr}
	runtime.SetFinalizer(obj, (*WilliamsR).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *WilliamsR) WarmupPeriod() int {
	r := int(C.wickra_williams_r_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *WilliamsR) IsReady() bool {
	r := bool(C.wickra_williams_r_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *WilliamsR) Name() string {
	r := C.GoString(C.wickra_williams_r_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *WilliamsR) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_williams_r_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *WilliamsR) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_williams_r_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *WilliamsR) Reset() {
	C.wickra_williams_r_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *WilliamsR) Close() {
	if ind.handle != nil {
		C.wickra_williams_r_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// WinRate wraps the WinRate indicator over the Wickra C ABI.
type WinRate struct {
	handle *C.struct_WinRate
}

// NewWinRate constructs a WinRate. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewWinRate(period int) (*WinRate, error) {
	ptr := C.wickra_win_rate_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &WinRate{handle: ptr}
	runtime.SetFinalizer(obj, (*WinRate).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *WinRate) WarmupPeriod() int {
	r := int(C.wickra_win_rate_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *WinRate) IsReady() bool {
	r := bool(C.wickra_win_rate_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *WinRate) Name() string {
	r := C.GoString(C.wickra_win_rate_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *WinRate) Update(value float64) float64 {
	r := float64(C.wickra_win_rate_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *WinRate) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_win_rate_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *WinRate) Reset() {
	C.wickra_win_rate_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *WinRate) Close() {
	if ind.handle != nil {
		C.wickra_win_rate_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Wma wraps the Wma indicator over the Wickra C ABI.
type Wma struct {
	handle *C.struct_Wma
}

// NewWma constructs a Wma. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewWma(period int) (*Wma, error) {
	ptr := C.wickra_wma_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Wma{handle: ptr}
	runtime.SetFinalizer(obj, (*Wma).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Wma) WarmupPeriod() int {
	r := int(C.wickra_wma_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Wma) IsReady() bool {
	r := bool(C.wickra_wma_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Wma) Name() string {
	r := C.GoString(C.wickra_wma_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Wma) Update(value float64) float64 {
	r := float64(C.wickra_wma_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Wma) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_wma_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Wma) Reset() {
	C.wickra_wma_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Wma) Close() {
	if ind.handle != nil {
		C.wickra_wma_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// WoodiePivots wraps the WoodiePivots indicator over the Wickra C ABI.
type WoodiePivots struct {
	handle *C.struct_WoodiePivots
}

// NewWoodiePivots constructs a WoodiePivots. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewWoodiePivots() (*WoodiePivots, error) {
	ptr := C.wickra_woodie_pivots_new()
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &WoodiePivots{handle: ptr}
	runtime.SetFinalizer(obj, (*WoodiePivots).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *WoodiePivots) WarmupPeriod() int {
	r := int(C.wickra_woodie_pivots_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *WoodiePivots) IsReady() bool {
	r := bool(C.wickra_woodie_pivots_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *WoodiePivots) Name() string {
	r := C.GoString(C.wickra_woodie_pivots_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *WoodiePivots) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (WoodiePivotsOutput, bool) {
	var out C.struct_WickraWoodiePivotsOutput
	ok := bool(C.wickra_woodie_pivots_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return WoodiePivotsOutput{}, false
	}
	return WoodiePivotsOutput{float64(out.pp), float64(out.r1), float64(out.r2), float64(out.s1), float64(out.s2)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *WoodiePivots) Reset() {
	C.wickra_woodie_pivots_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *WoodiePivots) Close() {
	if ind.handle != nil {
		C.wickra_woodie_pivots_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// YangZhangVolatility wraps the YangZhangVolatility indicator over the Wickra C ABI.
type YangZhangVolatility struct {
	handle *C.struct_YangZhangVolatility
}

// NewYangZhangVolatility constructs a YangZhangVolatility. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewYangZhangVolatility(period int, tradingPeriods int) (*YangZhangVolatility, error) {
	ptr := C.wickra_yang_zhang_volatility_new(C.uintptr_t(period), C.uintptr_t(tradingPeriods))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &YangZhangVolatility{handle: ptr}
	runtime.SetFinalizer(obj, (*YangZhangVolatility).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *YangZhangVolatility) WarmupPeriod() int {
	r := int(C.wickra_yang_zhang_volatility_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *YangZhangVolatility) IsReady() bool {
	r := bool(C.wickra_yang_zhang_volatility_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *YangZhangVolatility) Name() string {
	r := C.GoString(C.wickra_yang_zhang_volatility_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *YangZhangVolatility) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_yang_zhang_volatility_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *YangZhangVolatility) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_yang_zhang_volatility_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *YangZhangVolatility) Reset() {
	C.wickra_yang_zhang_volatility_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *YangZhangVolatility) Close() {
	if ind.handle != nil {
		C.wickra_yang_zhang_volatility_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// YoyoExit wraps the YoyoExit indicator over the Wickra C ABI.
type YoyoExit struct {
	handle *C.struct_YoyoExit
}

// NewYoyoExit constructs a YoyoExit. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewYoyoExit(atrPeriod int, multiplier float64) (*YoyoExit, error) {
	ptr := C.wickra_yoyo_exit_new(C.uintptr_t(atrPeriod), C.double(multiplier))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &YoyoExit{handle: ptr}
	runtime.SetFinalizer(obj, (*YoyoExit).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *YoyoExit) WarmupPeriod() int {
	r := int(C.wickra_yoyo_exit_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *YoyoExit) IsReady() bool {
	r := bool(C.wickra_yoyo_exit_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *YoyoExit) Name() string {
	r := C.GoString(C.wickra_yoyo_exit_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *YoyoExit) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) float64 {
	r := float64(C.wickra_yoyo_exit_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *YoyoExit) Batch(open []float64, high []float64, low []float64, close []float64, volume []float64, timestamp []int64) []float64 {
	n := len(open)
	if len(high) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(low) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(close) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(volume) != n {
		panic("wickra: all input slices must have the same length")
	}
	if len(timestamp) != n {
		panic("wickra: all input slices must have the same length")
	}
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_yoyo_exit_batch(ind.handle, (*C.double)(unsafe.Pointer(&open[0])), (*C.double)(unsafe.Pointer(&high[0])), (*C.double)(unsafe.Pointer(&low[0])), (*C.double)(unsafe.Pointer(&close[0])), (*C.double)(unsafe.Pointer(&volume[0])), (*C.int64_t)(unsafe.Pointer(&timestamp[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(open)
	runtime.KeepAlive(high)
	runtime.KeepAlive(low)
	runtime.KeepAlive(close)
	runtime.KeepAlive(volume)
	runtime.KeepAlive(timestamp)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *YoyoExit) Reset() {
	C.wickra_yoyo_exit_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *YoyoExit) Close() {
	if ind.handle != nil {
		C.wickra_yoyo_exit_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ZScore wraps the ZScore indicator over the Wickra C ABI.
type ZScore struct {
	handle *C.struct_ZScore
}

// NewZScore constructs a ZScore. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewZScore(period int) (*ZScore, error) {
	ptr := C.wickra_z_score_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ZScore{handle: ptr}
	runtime.SetFinalizer(obj, (*ZScore).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ZScore) WarmupPeriod() int {
	r := int(C.wickra_z_score_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ZScore) IsReady() bool {
	r := bool(C.wickra_z_score_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ZScore) Name() string {
	r := C.GoString(C.wickra_z_score_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *ZScore) Update(value float64) float64 {
	r := float64(C.wickra_z_score_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *ZScore) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_z_score_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ZScore) Reset() {
	C.wickra_z_score_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ZScore) Close() {
	if ind.handle != nil {
		C.wickra_z_score_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ZeroLagMacd wraps the ZeroLagMacd indicator over the Wickra C ABI.
type ZeroLagMacd struct {
	handle *C.struct_ZeroLagMacd
}

// NewZeroLagMacd constructs a ZeroLagMacd. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewZeroLagMacd(fast int, slow int, signal int) (*ZeroLagMacd, error) {
	ptr := C.wickra_zero_lag_macd_new(C.uintptr_t(fast), C.uintptr_t(slow), C.uintptr_t(signal))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ZeroLagMacd{handle: ptr}
	runtime.SetFinalizer(obj, (*ZeroLagMacd).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ZeroLagMacd) WarmupPeriod() int {
	r := int(C.wickra_zero_lag_macd_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ZeroLagMacd) IsReady() bool {
	r := bool(C.wickra_zero_lag_macd_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ZeroLagMacd) Name() string {
	r := C.GoString(C.wickra_zero_lag_macd_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *ZeroLagMacd) Update(value float64) (ZeroLagMacdOutput, bool) {
	var out C.struct_WickraZeroLagMacdOutput
	ok := bool(C.wickra_zero_lag_macd_update(ind.handle, C.double(value), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return ZeroLagMacdOutput{}, false
	}
	return ZeroLagMacdOutput{float64(out.macd), float64(out.signal), float64(out.histogram)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ZeroLagMacd) Reset() {
	C.wickra_zero_lag_macd_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ZeroLagMacd) Close() {
	if ind.handle != nil {
		C.wickra_zero_lag_macd_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ZigZag wraps the ZigZag indicator over the Wickra C ABI.
type ZigZag struct {
	handle *C.struct_ZigZag
}

// NewZigZag constructs a ZigZag. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewZigZag(threshold float64) (*ZigZag, error) {
	ptr := C.wickra_zig_zag_new(C.double(threshold))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &ZigZag{handle: ptr}
	runtime.SetFinalizer(obj, (*ZigZag).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *ZigZag) WarmupPeriod() int {
	r := int(C.wickra_zig_zag_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *ZigZag) IsReady() bool {
	r := bool(C.wickra_zig_zag_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *ZigZag) Name() string {
	r := C.GoString(C.wickra_zig_zag_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation. The bool reports whether a value is
// available yet (false during warmup).
func (ind *ZigZag) Update(open float64, high float64, low float64, close float64, volume float64, timestamp int64) (ZigZagOutput, bool) {
	var out C.struct_WickraZigZagOutput
	ok := bool(C.wickra_zig_zag_update(ind.handle, C.double(open), C.double(high), C.double(low), C.double(close), C.double(volume), C.int64_t(timestamp), &out))
	runtime.KeepAlive(ind)
	if !ok {
		return ZigZagOutput{}, false
	}
	return ZigZagOutput{float64(out.swing), float64(out.direction)}, true
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *ZigZag) Reset() {
	C.wickra_zig_zag_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *ZigZag) Close() {
	if ind.handle != nil {
		C.wickra_zig_zag_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// Zlema wraps the Zlema indicator over the Wickra C ABI.
type Zlema struct {
	handle *C.struct_Zlema
}

// NewZlema constructs a Zlema. It returns ErrInvalidParams when the
// native constructor rejects the arguments.
func NewZlema(period int) (*Zlema, error) {
	ptr := C.wickra_zlema_new(C.uintptr_t(period))
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &Zlema{handle: ptr}
	runtime.SetFinalizer(obj, (*Zlema).Close)
	return obj, nil
}

// WarmupPeriod returns the number of updates required before Update
// yields a non-NaN value.
func (ind *Zlema) WarmupPeriod() int {
	r := int(C.wickra_zlema_warmup_period(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// IsReady reports whether the indicator has consumed enough input to
// emit a value.
func (ind *Zlema) IsReady() bool {
	r := bool(C.wickra_zlema_is_ready(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Name returns the indicator's canonical name.
func (ind *Zlema) Name() string {
	r := C.GoString(C.wickra_zlema_name(ind.handle))
	runtime.KeepAlive(ind)
	return r
}

// Update feeds one observation and returns the indicator value
// (NaN until warmed up).
func (ind *Zlema) Update(value float64) float64 {
	r := float64(C.wickra_zlema_update(ind.handle, C.double(value)))
	runtime.KeepAlive(ind)
	return r
}

// Batch runs the indicator over a whole slice in one FFI call and
// returns the per-element output (NaN during warmup).
func (ind *Zlema) Batch(input []float64) []float64 {
	n := len(input)
	out := make([]float64, n)
	if n == 0 {
		return out
	}
	C.wickra_zlema_batch(ind.handle, (*C.double)(unsafe.Pointer(&input[0])), (*C.double)(unsafe.Pointer(&out[0])), C.uintptr_t(n))
	runtime.KeepAlive(ind)
	runtime.KeepAlive(input)
	return out
}

// Reset clears all internal state, returning the indicator to warmup.
func (ind *Zlema) Reset() {
	C.wickra_zlema_reset(ind.handle)
	runtime.KeepAlive(ind)
}

// Close frees the native handle. It is idempotent and safe to call
// alongside the finalizer.
func (ind *Zlema) Close() {
	if ind.handle != nil {
		C.wickra_zlema_free(ind.handle)
		ind.handle = nil
		runtime.SetFinalizer(ind, nil)
	}
}

// ===== Live Binance kline feed (feature `live-binance`) =====

// BinanceInterval selects a kline interval (the Interval declaration order).
type BinanceInterval uint8

// Kline intervals supported by the live Binance feed.
const (
	OneSecond BinanceInterval = iota
	OneMinute
	ThreeMinutes
	FiveMinutes
	FifteenMinutes
	ThirtyMinutes
	OneHour
	TwoHours
	FourHours
	SixHours
	EightHours
	TwelveHours
	OneDay
	ThreeDays
	OneWeek
	OneMonth
)

// KlineEvent is one event from the live Binance feed.
type KlineEvent struct {
	Symbol   string
	Open     float64
	High     float64
	Low      float64
	Close    float64
	Volume   float64
	OpenTime int64
	IsClosed bool
}

// BinanceFeed is a live Binance kline stream over the Wickra C ABI.
type BinanceFeed struct {
	handle *C.struct_BinanceStream
}

// NewBinanceFeed connects to Binance's live kline stream for the given
// comma-separated symbols (case-insensitive) at interval. baseURL overrides
// the endpoint ("" = production wss://stream.binance.com:9443; pass a ws://
// URL to target a test server). It returns ErrInvalidParams on a bad symbol
// list, an unknown interval, a bad URL, or a failed initial connect.
func NewBinanceFeed(symbols string, interval BinanceInterval, baseURL string) (*BinanceFeed, error) {
	csym := C.CString(symbols)
	defer C.free(unsafe.Pointer(csym))
	var curl *C.char
	if baseURL != "" {
		curl = C.CString(baseURL)
		defer C.free(unsafe.Pointer(curl))
	}
	ptr := C.wickra_binance_connect(csym, C.uint8_t(interval), curl)
	if ptr == nil {
		return nil, ErrInvalidParams
	}
	obj := &BinanceFeed{handle: ptr}
	runtime.SetFinalizer(obj, (*BinanceFeed).Close)
	return obj, nil
}

// Next polls for the next kline event, waiting up to timeout. It returns the
// event and true when one arrives, the zero value and false on timeout, or
// ErrFeedClosed once the stream is closed or has errored out.
func (f *BinanceFeed) Next(timeout time.Duration) (KlineEvent, bool, error) {
	var ev C.struct_WickraKlineEvent
	code := int(C.wickra_binance_next(f.handle, &ev, C.int64_t(timeout.Milliseconds())))
	runtime.KeepAlive(f)
	switch code {
	case 1:
		return klineFromC(&ev), true, nil
	case 0:
		return KlineEvent{}, false, nil
	default:
		return KlineEvent{}, false, ErrFeedClosed
	}
}

func klineFromC(ev *C.struct_WickraKlineEvent) KlineEvent {
	n := 0
	for n < len(ev.symbol) && ev.symbol[n] != 0 {
		n++
	}
	sym := C.GoBytes(unsafe.Pointer(&ev.symbol[0]), C.int(n))
	return KlineEvent{
		Symbol:   string(sym),
		Open:     float64(ev.open),
		High:     float64(ev.high),
		Low:      float64(ev.low),
		Close:    float64(ev.close),
		Volume:   float64(ev.volume),
		OpenTime: int64(ev.open_time),
		IsClosed: bool(ev.is_closed),
	}
}

// Close ends the stream and frees the native handle. Idempotent and safe to
// call alongside the finalizer.
func (f *BinanceFeed) Close() {
	if f.handle != nil {
		C.wickra_binance_close(f.handle)
		C.wickra_binance_free(f.handle)
		f.handle = nil
		runtime.SetFinalizer(f, nil)
	}
}

// FetchBinanceKlines fetches historical klines from Binance's REST endpoint.
// symbol is the trading pair (case-insensitive), interval the kline interval,
// and limit the number of candles to request (1..=1000). startMs/endMs are
// inclusive Unix-millisecond bounds (negative = unset); baseURL overrides the
// host ("" = production https://api.binance.com). It blocks until the response
// arrives and returns ErrInvalidParams on a bad argument or transport error.
func FetchBinanceKlines(symbol string, interval BinanceInterval, limit uint32, startMs, endMs int64, baseURL string) ([]Candle, error) {
	if limit == 0 {
		return nil, ErrInvalidParams
	}
	csym := C.CString(symbol)
	defer C.free(unsafe.Pointer(csym))
	var curl *C.char
	if baseURL != "" {
		curl = C.CString(baseURL)
		defer C.free(unsafe.Pointer(curl))
	}
	buf := make([]C.struct_WickraCandle, limit)
	n := int(C.wickra_binance_fetch_klines(csym, C.uint8_t(interval), C.uint32_t(limit), C.int64_t(startMs), C.int64_t(endMs), curl, &buf[0], C.uintptr_t(limit)))
	if n < 0 {
		return nil, ErrInvalidParams
	}
	out := make([]Candle, n)
	for i := 0; i < n; i++ {
		out[i] = Candle{float64(buf[i].open), float64(buf[i].high), float64(buf[i].low), float64(buf[i].close), float64(buf[i].volume), int64(buf[i].timestamp)}
	}
	return out, nil
}
