d362ae26a3
Add the data-layer CSV candle reader to every binding so loading OHLCV candles from a CSV no longer needs a per-language CSV/dataframe dependency. - C ABI: wickra_candle_reader_new(bytes, len) / _count / _read / _free over an opaque CandleReader handle (parse the whole buffer up front, then drain). - Native: Node/WASM CandleReader.read() -> Candle[], Python read() -> list[tuple]. - C-ABI languages: Go Read() []Candle, C# Candle[] Read(), Java Candle[] read(), R read() S3 generic (n x 6 matrix); C / C++ call the C ABI directly. - Cross-language golden testdata/golden/data_csv*.csv pins the parsed candles bit-for-bit across every binding. Verified locally across Rust (test+clippy+fmt), Node, WASM, Python, C#, Go, Java, R, and the C/C++ cmake parity suite.
41511 lines
1.3 MiB
Plaintext
41511 lines
1.3 MiB
Plaintext
// <auto-generated />
|
|
// Generated from bindings/c/include/wickra.h. Do not edit by hand.
|
|
#nullable enable
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace Wickra;
|
|
|
|
public readonly record struct AccelerationBandsOutput(double Upper, double Middle, double Lower);
|
|
public readonly record struct AdxOutput(double PlusDi, double MinusDi, double Adx);
|
|
public readonly record struct AlligatorOutput(double Jaw, double Teeth, double Lips);
|
|
public readonly record struct AndrewsPitchforkOutput(double Median, double Upper, double Lower);
|
|
public readonly record struct AroonOutput(double Up, double Down);
|
|
public readonly record struct AtrBandsOutput(double Upper, double Middle, double Lower);
|
|
public readonly record struct AtrRatchetOutput(double Value, double Direction);
|
|
public readonly record struct AutoFibOutput(double Level0, double Level236, double Level382, double Level500, double Level618, double Level786, double Level1000);
|
|
public readonly record struct BollingerOutput(double Upper, double Middle, double Lower, double Stddev);
|
|
public readonly record struct BomarBandsOutput(double Upper, double Middle, double Lower);
|
|
public readonly record struct CamarillaPivotsOutput(double Pp, double R1, double R2, double R3, double R4, double S1, double S2, double S3, double S4);
|
|
public readonly record struct Candle(double Open, double High, double Low, double Close, double Volume, double Timestamp);
|
|
public readonly record struct CandleVolumeOutput(double Body, double Width);
|
|
public readonly record struct CentralPivotRangeOutput(double Pivot, double Tc, double Bc);
|
|
public readonly record struct ChandeKrollStopOutput(double StopLong, double StopShort);
|
|
public readonly record struct ChandelierExitOutput(double LongStop, double ShortStop);
|
|
public readonly record struct ClassicPivotsOutput(double Pp, double R1, double R2, double R3, double S1, double S2, double S3);
|
|
public readonly record struct CointegrationOutput(double HedgeRatio, double Spread, double AdfStat);
|
|
public readonly record struct CompositeProfileOutput(double Poc, double Vah, double Val);
|
|
public readonly record struct DemarkPivotsOutput(double Pp, double R1, double S1);
|
|
public readonly record struct DollarBar(double Open, double High, double Low, double Close, double Volume, double Dollar);
|
|
public readonly record struct DonchianOutput(double Upper, double Middle, double Lower);
|
|
public readonly record struct DonchianStopOutput(double StopLong, double StopShort);
|
|
public readonly record struct DoubleBollingerOutput(double UpperOuter, double UpperInner, double Middle, double LowerInner, double LowerOuter);
|
|
public readonly record struct ElderRayOutput(double BullPower, double BearPower);
|
|
public readonly record struct ElderSafeZoneOutput(double Value, double Direction);
|
|
public readonly record struct EquivolumeOutput(double Height, double Width);
|
|
public readonly record struct FibArcsOutput(double Arc382, double Arc500, double Arc618);
|
|
public readonly record struct FibChannelOutput(double Base, double Level618, double Level1000, double Level1618);
|
|
public readonly record struct FibConfluenceOutput(double Price, double Strength);
|
|
public readonly record struct FibExtensionOutput(double Level1272, double Level1414, double Level1618, double Level2000, double Level2618);
|
|
public readonly record struct FibFanOutput(double Fan382, double Fan500, double Fan618);
|
|
public readonly record struct FibProjectionOutput(double Level618, double Level1000, double Level1618, double Level2618);
|
|
public readonly record struct FibRetracementOutput(double Level0, double Level236, double Level382, double Level500, double Level618, double Level786, double Level1000);
|
|
public readonly record struct FibTimeZonesOutput(double OnZone, double BarsToNext);
|
|
public readonly record struct FibonacciPivotsOutput(double Pp, double R1, double R2, double R3, double S1, double S2, double S3);
|
|
public readonly record struct FootprintLevel(double Price, double BidVol, double AskVol);
|
|
public readonly record struct FractalChaosBandsOutput(double Upper, double Lower);
|
|
public readonly record struct GatorOscillatorOutput(double Upper, double Lower);
|
|
public readonly record struct GoldenPocketOutput(double Low, double Mid, double High);
|
|
public readonly record struct HeikinAshiOutput(double Open, double High, double Low, double Close);
|
|
public readonly record struct HighLowVolumeNodesOutput(double Hvn, double Lvn);
|
|
public readonly record struct HtPhasorOutput(double Inphase, double Quadrature);
|
|
public readonly record struct HurstChannelOutput(double Upper, double Middle, double Lower);
|
|
public readonly record struct IchimokuOutput(double Tenkan, double Kijun, double SenkouA, double SenkouB, double Chikou);
|
|
public readonly record struct ImbalanceBar(double Open, double High, double Low, double Close, double Imbalance, double Direction);
|
|
public readonly record struct InitialBalanceOutput(double High, double Low);
|
|
public readonly record struct KagiBar(double Start, double End, double Direction);
|
|
public readonly record struct KalmanHedgeRatioOutput(double HedgeRatio, double Intercept, double Spread);
|
|
public readonly record struct KaseDevStopOutput(double Value, double Direction);
|
|
public readonly record struct KasePermissionStochasticOutput(double Fast, double Slow);
|
|
public readonly record struct KeltnerOutput(double Upper, double Middle, double Lower);
|
|
public readonly record struct KstOutput(double Kst, double Signal);
|
|
public readonly record struct LeadLagCrossCorrelationOutput(double Lag, double Correlation);
|
|
public readonly record struct LinRegChannelOutput(double Upper, double Middle, double Lower);
|
|
public readonly record struct LineBreakBar(double Open, double Close, double Direction);
|
|
public readonly record struct LiquidationFeaturesOutput(double Long, double Short, double Net, double Total, double Imbalance);
|
|
public readonly record struct MaEnvelopeOutput(double Upper, double Middle, double Lower);
|
|
public readonly record struct MacdOutput(double Macd, double Signal, double Histogram);
|
|
public readonly record struct MamaOutput(double Mama, double Fama);
|
|
public readonly record struct MedianChannelOutput(double Upper, double Middle, double Lower);
|
|
public readonly record struct ModifiedMaStopOutput(double Value, double Direction);
|
|
public readonly record struct MurreyMathLinesOutput(double Mm88, double Mm78, double Mm68, double Mm58, double Mm48, double Mm38, double Mm28, double Mm18, double Mm08);
|
|
public readonly record struct NrtrOutput(double Value, double Direction);
|
|
public readonly record struct OpeningRangeOutput(double High, double Low, double BreakoutDistance);
|
|
public readonly record struct OvernightIntradayReturnOutput(double Overnight, double Intraday);
|
|
public readonly record struct PnfColumn(double Direction, double High, double Low);
|
|
public readonly record struct ProjectionBandsOutput(double Upper, double Middle, double Lower);
|
|
public readonly record struct QqeOutput(double RsiMa, double TrailingLine);
|
|
public readonly record struct QuartileBandsOutput(double Upper, double Middle, double Lower);
|
|
public readonly record struct RangeBar(double Open, double Close, double Direction);
|
|
public readonly record struct RelativeStrengthOutput(double Ratio, double RatioMa, double RatioRsi);
|
|
public readonly record struct RenkoBrick(double Open, double Close, double Direction);
|
|
public readonly record struct RunBar(double Open, double High, double Low, double Close, double Length, double Direction);
|
|
public readonly record struct RwiOutput(double High, double Low);
|
|
public readonly record struct SessionHighLowOutput(double High, double Low);
|
|
public readonly record struct SessionRangeOutput(double Asia, double Eu, double Us);
|
|
public readonly record struct SmoothedHeikinAshiOutput(double Open, double High, double Low, double Close);
|
|
public readonly record struct SpreadBollingerBandsOutput(double Middle, double Upper, double Lower, double PercentB);
|
|
public readonly record struct StandardErrorBandsOutput(double Upper, double Middle, double Lower);
|
|
public readonly record struct StarcBandsOutput(double Upper, double Middle, double Lower);
|
|
public readonly record struct StochasticOutput(double K, double D);
|
|
public readonly record struct SuperTrendOutput(double Value, double Direction);
|
|
public readonly record struct TdLinesOutput(double Resistance, double Support);
|
|
public readonly record struct TdMovingAverageOutput(double St1, double St2);
|
|
public readonly record struct TdRangeProjectionOutput(double High, double Low);
|
|
public readonly record struct TdRiskLevelOutput(double BuyRisk, double SellRisk);
|
|
public readonly record struct TdSequentialOutput(double Setup, double Countdown, double Direction);
|
|
public readonly record struct TickBar(double Open, double High, double Low, double Close, double Volume);
|
|
public readonly record struct TpoProfileOutputScalars(double PriceLow, double PriceHigh, double[] Values);
|
|
public readonly record struct TtmSqueezeOutput(double Squeeze, double Momentum);
|
|
public readonly record struct ValueAreaOutput(double Poc, double Vah, double Val);
|
|
public readonly record struct VolatilityConeOutput(double Current, double Min, double Median, double Max, double Percentile);
|
|
public readonly record struct VolumeBar(double Open, double High, double Low, double Close, double Volume);
|
|
public readonly record struct VolumeProfileOutputScalars(double PriceLow, double PriceHigh, double[] Values);
|
|
public readonly record struct VolumeWeightedMacdOutput(double Macd, double Signal, double Histogram);
|
|
public readonly record struct VolumeWeightedSrOutput(double Support, double Resistance);
|
|
public readonly record struct VortexOutput(double Plus, double Minus);
|
|
public readonly record struct VwapStdDevBandsOutput(double Upper, double Middle, double Lower, double Stddev);
|
|
public readonly record struct WaveTrendOutput(double Wt1, double Wt2);
|
|
public readonly record struct WilliamsFractalsOutput(double Up, double Down);
|
|
public readonly record struct WoodiePivotsOutput(double Pp, double R1, double R2, double S1, double S2);
|
|
public readonly record struct ZeroLagMacdOutput(double Macd, double Signal, double Histogram);
|
|
public readonly record struct ZigZagOutput(double Swing, double Direction);
|
|
|
|
public sealed class AbandonedBaby : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AbandonedBaby()
|
|
{
|
|
var ptr = NativeMethods.wickra_abandoned_baby_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AbandonedBaby parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_abandoned_baby_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_abandoned_baby_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_abandoned_baby_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_abandoned_baby_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_abandoned_baby_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_abandoned_baby_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_abandoned_baby_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Abcd : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Abcd()
|
|
{
|
|
var ptr = NativeMethods.wickra_abcd_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Abcd parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_abcd_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_abcd_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_abcd_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_abcd_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_abcd_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_abcd_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_abcd_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AbsoluteBreadthIndex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AbsoluteBreadthIndex()
|
|
{
|
|
var ptr = NativeMethods.wickra_absolute_breadth_index_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AbsoluteBreadthIndex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_absolute_breadth_index_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> change, ReadOnlySpan<double> volume, ReadOnlySpan<bool> newHigh, ReadOnlySpan<bool> newLow, ReadOnlySpan<bool> aboveMa, ReadOnlySpan<bool> onBuySignal, long timestamp)
|
|
{
|
|
if (volume.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newHigh.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newLow.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (aboveMa.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (onBuySignal.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* changePtr = change)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (bool* newHighPtr = newHigh)
|
|
fixed (bool* newLowPtr = newLow)
|
|
fixed (bool* aboveMaPtr = aboveMa)
|
|
fixed (bool* onBuySignalPtr = onBuySignal)
|
|
{
|
|
result = NativeMethods.wickra_absolute_breadth_index_update(_handle.DangerousGetHandle(), changePtr, volumePtr, newHighPtr, newLowPtr, aboveMaPtr, onBuySignalPtr, (nuint)change.Length, timestamp);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_absolute_breadth_index_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_absolute_breadth_index_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_absolute_breadth_index_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_absolute_breadth_index_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AccelerationBands : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AccelerationBands(int period, double factor)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_acceleration_bands_new((nuint)period, factor);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AccelerationBands parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_acceleration_bands_free);
|
|
}
|
|
|
|
public AccelerationBandsOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraAccelerationBandsOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_acceleration_bands_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new AccelerationBandsOutput(native.upper, native.middle, native.lower) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_acceleration_bands_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_acceleration_bands_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_acceleration_bands_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_acceleration_bands_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AcceleratorOscillator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AcceleratorOscillator(int aoFast, int aoSlow, int signalPeriod)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(aoFast);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(aoSlow);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(signalPeriod);
|
|
var ptr = NativeMethods.wickra_accelerator_oscillator_new((nuint)aoFast, (nuint)aoSlow, (nuint)signalPeriod);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AcceleratorOscillator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_accelerator_oscillator_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_accelerator_oscillator_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_accelerator_oscillator_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_accelerator_oscillator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_accelerator_oscillator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_accelerator_oscillator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_accelerator_oscillator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AdOscillator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AdOscillator()
|
|
{
|
|
var ptr = NativeMethods.wickra_ad_oscillator_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AdOscillator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ad_oscillator_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_ad_oscillator_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_ad_oscillator_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ad_oscillator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ad_oscillator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ad_oscillator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ad_oscillator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AdVolumeLine : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AdVolumeLine()
|
|
{
|
|
var ptr = NativeMethods.wickra_ad_volume_line_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AdVolumeLine parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ad_volume_line_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> change, ReadOnlySpan<double> volume, ReadOnlySpan<bool> newHigh, ReadOnlySpan<bool> newLow, ReadOnlySpan<bool> aboveMa, ReadOnlySpan<bool> onBuySignal, long timestamp)
|
|
{
|
|
if (volume.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newHigh.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newLow.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (aboveMa.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (onBuySignal.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* changePtr = change)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (bool* newHighPtr = newHigh)
|
|
fixed (bool* newLowPtr = newLow)
|
|
fixed (bool* aboveMaPtr = aboveMa)
|
|
fixed (bool* onBuySignalPtr = onBuySignal)
|
|
{
|
|
result = NativeMethods.wickra_ad_volume_line_update(_handle.DangerousGetHandle(), changePtr, volumePtr, newHighPtr, newLowPtr, aboveMaPtr, onBuySignalPtr, (nuint)change.Length, timestamp);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ad_volume_line_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ad_volume_line_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ad_volume_line_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ad_volume_line_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AdaptiveCci : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AdaptiveCci(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_adaptive_cci_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AdaptiveCci parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_adaptive_cci_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_adaptive_cci_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_adaptive_cci_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_adaptive_cci_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_adaptive_cci_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_adaptive_cci_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_adaptive_cci_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AdaptiveCycle : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AdaptiveCycle()
|
|
{
|
|
var ptr = NativeMethods.wickra_adaptive_cycle_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AdaptiveCycle parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_adaptive_cycle_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_adaptive_cycle_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_adaptive_cycle_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_adaptive_cycle_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_adaptive_cycle_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_adaptive_cycle_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_adaptive_cycle_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AdaptiveLaguerreFilter : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AdaptiveLaguerreFilter(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_adaptive_laguerre_filter_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AdaptiveLaguerreFilter parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_adaptive_laguerre_filter_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_adaptive_laguerre_filter_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_adaptive_laguerre_filter_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_adaptive_laguerre_filter_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_adaptive_laguerre_filter_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_adaptive_laguerre_filter_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_adaptive_laguerre_filter_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AdaptiveRsi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AdaptiveRsi(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_adaptive_rsi_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AdaptiveRsi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_adaptive_rsi_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_adaptive_rsi_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_adaptive_rsi_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_adaptive_rsi_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_adaptive_rsi_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_adaptive_rsi_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_adaptive_rsi_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Adl : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Adl()
|
|
{
|
|
var ptr = NativeMethods.wickra_adl_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Adl parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_adl_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_adl_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_adl_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_adl_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_adl_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_adl_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_adl_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AdvanceBlock : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AdvanceBlock()
|
|
{
|
|
var ptr = NativeMethods.wickra_advance_block_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AdvanceBlock parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_advance_block_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_advance_block_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_advance_block_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_advance_block_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_advance_block_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_advance_block_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_advance_block_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AdvanceDecline : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AdvanceDecline()
|
|
{
|
|
var ptr = NativeMethods.wickra_advance_decline_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AdvanceDecline parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_advance_decline_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> change, ReadOnlySpan<double> volume, ReadOnlySpan<bool> newHigh, ReadOnlySpan<bool> newLow, ReadOnlySpan<bool> aboveMa, ReadOnlySpan<bool> onBuySignal, long timestamp)
|
|
{
|
|
if (volume.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newHigh.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newLow.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (aboveMa.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (onBuySignal.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* changePtr = change)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (bool* newHighPtr = newHigh)
|
|
fixed (bool* newLowPtr = newLow)
|
|
fixed (bool* aboveMaPtr = aboveMa)
|
|
fixed (bool* onBuySignalPtr = onBuySignal)
|
|
{
|
|
result = NativeMethods.wickra_advance_decline_update(_handle.DangerousGetHandle(), changePtr, volumePtr, newHighPtr, newLowPtr, aboveMaPtr, onBuySignalPtr, (nuint)change.Length, timestamp);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_advance_decline_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_advance_decline_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_advance_decline_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_advance_decline_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AdvanceDeclineRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AdvanceDeclineRatio()
|
|
{
|
|
var ptr = NativeMethods.wickra_advance_decline_ratio_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AdvanceDeclineRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_advance_decline_ratio_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> change, ReadOnlySpan<double> volume, ReadOnlySpan<bool> newHigh, ReadOnlySpan<bool> newLow, ReadOnlySpan<bool> aboveMa, ReadOnlySpan<bool> onBuySignal, long timestamp)
|
|
{
|
|
if (volume.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newHigh.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newLow.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (aboveMa.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (onBuySignal.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* changePtr = change)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (bool* newHighPtr = newHigh)
|
|
fixed (bool* newLowPtr = newLow)
|
|
fixed (bool* aboveMaPtr = aboveMa)
|
|
fixed (bool* onBuySignalPtr = onBuySignal)
|
|
{
|
|
result = NativeMethods.wickra_advance_decline_ratio_update(_handle.DangerousGetHandle(), changePtr, volumePtr, newHighPtr, newLowPtr, aboveMaPtr, onBuySignalPtr, (nuint)change.Length, timestamp);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_advance_decline_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_advance_decline_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_advance_decline_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_advance_decline_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Adx : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Adx(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_adx_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Adx parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_adx_free);
|
|
}
|
|
|
|
public AdxOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraAdxOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_adx_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new AdxOutput(native.plus_di, native.minus_di, native.adx) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_adx_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_adx_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_adx_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_adx_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Adxr : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Adxr(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_adxr_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Adxr parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_adxr_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_adxr_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_adxr_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_adxr_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_adxr_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_adxr_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_adxr_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Alligator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Alligator(int jawPeriod, int teethPeriod, int lipsPeriod)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(jawPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(teethPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(lipsPeriod);
|
|
var ptr = NativeMethods.wickra_alligator_new((nuint)jawPeriod, (nuint)teethPeriod, (nuint)lipsPeriod);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Alligator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_alligator_free);
|
|
}
|
|
|
|
public AlligatorOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraAlligatorOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_alligator_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new AlligatorOutput(native.jaw, native.teeth, native.lips) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_alligator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_alligator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_alligator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_alligator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Alma : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Alma(int period, double offset, double sigma)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_alma_new((nuint)period, offset, sigma);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Alma parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_alma_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_alma_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_alma_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_alma_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_alma_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_alma_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_alma_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Alpha : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Alpha(int period, double riskFree)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_alpha_new((nuint)period, riskFree);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Alpha parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_alpha_free);
|
|
}
|
|
|
|
public double Update(double x, double y)
|
|
{
|
|
var result = NativeMethods.wickra_alpha_update(_handle.DangerousGetHandle(), x, y);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> x, ReadOnlySpan<double> y)
|
|
{
|
|
var n = x.Length;
|
|
if (y.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* xPtr = x)
|
|
fixed (double* yPtr = y)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_alpha_batch(_handle.DangerousGetHandle(), xPtr, yPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_alpha_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_alpha_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_alpha_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_alpha_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AmihudIlliquidity : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AmihudIlliquidity(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_amihud_illiquidity_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AmihudIlliquidity parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_amihud_illiquidity_free);
|
|
}
|
|
|
|
public double Update(double price, double size, bool isBuy, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_amihud_illiquidity_update(_handle.DangerousGetHandle(), price, size, isBuy, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_amihud_illiquidity_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_amihud_illiquidity_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_amihud_illiquidity_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_amihud_illiquidity_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AnchoredRsi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AnchoredRsi()
|
|
{
|
|
var ptr = NativeMethods.wickra_anchored_rsi_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AnchoredRsi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_anchored_rsi_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_anchored_rsi_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_anchored_rsi_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_anchored_rsi_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_anchored_rsi_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_anchored_rsi_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_anchored_rsi_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AnchoredVwap : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AnchoredVwap()
|
|
{
|
|
var ptr = NativeMethods.wickra_anchored_vwap_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AnchoredVwap parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_anchored_vwap_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_anchored_vwap_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_anchored_vwap_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_anchored_vwap_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_anchored_vwap_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_anchored_vwap_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_anchored_vwap_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AndrewsPitchfork : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AndrewsPitchfork(int strength)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(strength);
|
|
var ptr = NativeMethods.wickra_andrews_pitchfork_new((nuint)strength);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AndrewsPitchfork parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_andrews_pitchfork_free);
|
|
}
|
|
|
|
public AndrewsPitchforkOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraAndrewsPitchforkOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_andrews_pitchfork_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new AndrewsPitchforkOutput(native.median, native.upper, native.lower) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_andrews_pitchfork_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_andrews_pitchfork_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_andrews_pitchfork_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_andrews_pitchfork_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Apo : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Apo(int fast, int slow)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(fast);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(slow);
|
|
var ptr = NativeMethods.wickra_apo_new((nuint)fast, (nuint)slow);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Apo parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_apo_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_apo_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_apo_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_apo_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_apo_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_apo_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_apo_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Aroon : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Aroon(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_aroon_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Aroon parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_aroon_free);
|
|
}
|
|
|
|
public AroonOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraAroonOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_aroon_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new AroonOutput(native.up, native.down) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_aroon_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_aroon_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_aroon_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_aroon_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AroonOscillator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AroonOscillator(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_aroon_oscillator_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AroonOscillator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_aroon_oscillator_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_aroon_oscillator_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_aroon_oscillator_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_aroon_oscillator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_aroon_oscillator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_aroon_oscillator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_aroon_oscillator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Atr : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Atr(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_atr_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Atr parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_atr_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_atr_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_atr_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_atr_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_atr_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_atr_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_atr_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AtrBands : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AtrBands(int period, double multiplier)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_atr_bands_new((nuint)period, multiplier);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AtrBands parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_atr_bands_free);
|
|
}
|
|
|
|
public AtrBandsOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraAtrBandsOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_atr_bands_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new AtrBandsOutput(native.upper, native.middle, native.lower) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_atr_bands_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_atr_bands_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_atr_bands_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_atr_bands_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AtrRatchet : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AtrRatchet(int atrPeriod, double startMult, double increment)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(atrPeriod);
|
|
var ptr = NativeMethods.wickra_atr_ratchet_new((nuint)atrPeriod, startMult, increment);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AtrRatchet parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_atr_ratchet_free);
|
|
}
|
|
|
|
public AtrRatchetOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraAtrRatchetOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_atr_ratchet_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new AtrRatchetOutput(native.@value, native.direction) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_atr_ratchet_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_atr_ratchet_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_atr_ratchet_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_atr_ratchet_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AtrTrailingStop : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AtrTrailingStop(int atrPeriod, double multiplier)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(atrPeriod);
|
|
var ptr = NativeMethods.wickra_atr_trailing_stop_new((nuint)atrPeriod, multiplier);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AtrTrailingStop parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_atr_trailing_stop_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_atr_trailing_stop_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_atr_trailing_stop_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_atr_trailing_stop_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_atr_trailing_stop_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_atr_trailing_stop_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_atr_trailing_stop_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AutoFib : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AutoFib()
|
|
{
|
|
var ptr = NativeMethods.wickra_auto_fib_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AutoFib parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_auto_fib_free);
|
|
}
|
|
|
|
public AutoFibOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraAutoFibOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_auto_fib_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new AutoFibOutput(native.level_0, native.level_236, native.level_382, native.level_500, native.level_618, native.level_786, native.level_1000) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_auto_fib_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_auto_fib_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_auto_fib_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_auto_fib_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Autocorrelation : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Autocorrelation(int period, int lag)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(lag);
|
|
var ptr = NativeMethods.wickra_autocorrelation_new((nuint)period, (nuint)lag);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Autocorrelation parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_autocorrelation_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_autocorrelation_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_autocorrelation_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_autocorrelation_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_autocorrelation_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_autocorrelation_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_autocorrelation_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AutocorrelationPeriodogram : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AutocorrelationPeriodogram(int minPeriod, int maxPeriod)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(minPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(maxPeriod);
|
|
var ptr = NativeMethods.wickra_autocorrelation_periodogram_new((nuint)minPeriod, (nuint)maxPeriod);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AutocorrelationPeriodogram parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_autocorrelation_periodogram_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_autocorrelation_periodogram_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_autocorrelation_periodogram_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_autocorrelation_periodogram_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_autocorrelation_periodogram_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_autocorrelation_periodogram_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_autocorrelation_periodogram_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AverageDailyRange : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AverageDailyRange(int period, int utcOffsetMinutes)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_average_daily_range_new((nuint)period, utcOffsetMinutes);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AverageDailyRange parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_average_daily_range_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_average_daily_range_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_average_daily_range_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_average_daily_range_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_average_daily_range_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_average_daily_range_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_average_daily_range_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AverageDrawdown : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AverageDrawdown(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_average_drawdown_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AverageDrawdown parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_average_drawdown_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_average_drawdown_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_average_drawdown_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_average_drawdown_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_average_drawdown_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_average_drawdown_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_average_drawdown_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AvgPrice : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AvgPrice()
|
|
{
|
|
var ptr = NativeMethods.wickra_avg_price_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AvgPrice parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_avg_price_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_avg_price_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_avg_price_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_avg_price_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_avg_price_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_avg_price_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_avg_price_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AwesomeOscillator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AwesomeOscillator(int fast, int slow)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(fast);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(slow);
|
|
var ptr = NativeMethods.wickra_awesome_oscillator_new((nuint)fast, (nuint)slow);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AwesomeOscillator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_awesome_oscillator_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_awesome_oscillator_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_awesome_oscillator_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_awesome_oscillator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_awesome_oscillator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_awesome_oscillator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_awesome_oscillator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class AwesomeOscillatorHistogram : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public AwesomeOscillatorHistogram(int fast, int slow, int lookback)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(fast);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(slow);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(lookback);
|
|
var ptr = NativeMethods.wickra_awesome_oscillator_histogram_new((nuint)fast, (nuint)slow, (nuint)lookback);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid AwesomeOscillatorHistogram parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_awesome_oscillator_histogram_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_awesome_oscillator_histogram_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_awesome_oscillator_histogram_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_awesome_oscillator_histogram_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_awesome_oscillator_histogram_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_awesome_oscillator_histogram_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_awesome_oscillator_histogram_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class BalanceOfPower : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public BalanceOfPower()
|
|
{
|
|
var ptr = NativeMethods.wickra_balance_of_power_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid BalanceOfPower parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_balance_of_power_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_balance_of_power_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_balance_of_power_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_balance_of_power_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_balance_of_power_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_balance_of_power_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_balance_of_power_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class BandpassFilter : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public BandpassFilter(int period, double bandwidth)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_bandpass_filter_new((nuint)period, bandwidth);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid BandpassFilter parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_bandpass_filter_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_bandpass_filter_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_bandpass_filter_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_bandpass_filter_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_bandpass_filter_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_bandpass_filter_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_bandpass_filter_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Bat : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Bat()
|
|
{
|
|
var ptr = NativeMethods.wickra_bat_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Bat parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_bat_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_bat_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_bat_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_bat_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_bat_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_bat_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_bat_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class BeltHold : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public BeltHold()
|
|
{
|
|
var ptr = NativeMethods.wickra_belt_hold_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid BeltHold parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_belt_hold_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_belt_hold_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_belt_hold_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_belt_hold_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_belt_hold_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_belt_hold_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_belt_hold_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Beta : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Beta(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_beta_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Beta parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_beta_free);
|
|
}
|
|
|
|
public double Update(double x, double y)
|
|
{
|
|
var result = NativeMethods.wickra_beta_update(_handle.DangerousGetHandle(), x, y);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> x, ReadOnlySpan<double> y)
|
|
{
|
|
var n = x.Length;
|
|
if (y.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* xPtr = x)
|
|
fixed (double* yPtr = y)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_beta_batch(_handle.DangerousGetHandle(), xPtr, yPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_beta_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_beta_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_beta_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_beta_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class BetaNeutralSpread : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public BetaNeutralSpread(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_beta_neutral_spread_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid BetaNeutralSpread parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_beta_neutral_spread_free);
|
|
}
|
|
|
|
public double Update(double x, double y)
|
|
{
|
|
var result = NativeMethods.wickra_beta_neutral_spread_update(_handle.DangerousGetHandle(), x, y);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> x, ReadOnlySpan<double> y)
|
|
{
|
|
var n = x.Length;
|
|
if (y.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* xPtr = x)
|
|
fixed (double* yPtr = y)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_beta_neutral_spread_batch(_handle.DangerousGetHandle(), xPtr, yPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_beta_neutral_spread_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_beta_neutral_spread_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_beta_neutral_spread_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_beta_neutral_spread_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class BetterVolume : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public BetterVolume(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_better_volume_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid BetterVolume parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_better_volume_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_better_volume_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_better_volume_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_better_volume_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_better_volume_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_better_volume_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_better_volume_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class BipowerVariation : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public BipowerVariation(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_bipower_variation_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid BipowerVariation parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_bipower_variation_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_bipower_variation_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_bipower_variation_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_bipower_variation_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_bipower_variation_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_bipower_variation_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_bipower_variation_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class BodySizePct : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public BodySizePct()
|
|
{
|
|
var ptr = NativeMethods.wickra_body_size_pct_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid BodySizePct parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_body_size_pct_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_body_size_pct_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_body_size_pct_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_body_size_pct_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_body_size_pct_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_body_size_pct_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_body_size_pct_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class BollingerBands : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public BollingerBands(int period, double multiplier)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_bollinger_bands_new((nuint)period, multiplier);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid BollingerBands parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_bollinger_bands_free);
|
|
}
|
|
|
|
public BollingerOutput? Update(double @value)
|
|
{
|
|
WickraBollingerOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_bollinger_bands_update(_handle.DangerousGetHandle(), @value, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new BollingerOutput(native.upper, native.middle, native.lower, native.stddev) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_bollinger_bands_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_bollinger_bands_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_bollinger_bands_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_bollinger_bands_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class BollingerBandwidth : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public BollingerBandwidth(int period, double multiplier)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_bollinger_bandwidth_new((nuint)period, multiplier);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid BollingerBandwidth parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_bollinger_bandwidth_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_bollinger_bandwidth_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_bollinger_bandwidth_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_bollinger_bandwidth_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_bollinger_bandwidth_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_bollinger_bandwidth_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_bollinger_bandwidth_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class BomarBands : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public BomarBands(int period, double coverage)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_bomar_bands_new((nuint)period, coverage);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid BomarBands parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_bomar_bands_free);
|
|
}
|
|
|
|
public BomarBandsOutput? Update(double @value)
|
|
{
|
|
WickraBomarBandsOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_bomar_bands_update(_handle.DangerousGetHandle(), @value, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new BomarBandsOutput(native.upper, native.middle, native.lower) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_bomar_bands_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_bomar_bands_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_bomar_bands_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_bomar_bands_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class BreadthThrust : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public BreadthThrust(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_breadth_thrust_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid BreadthThrust parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_breadth_thrust_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> change, ReadOnlySpan<double> volume, ReadOnlySpan<bool> newHigh, ReadOnlySpan<bool> newLow, ReadOnlySpan<bool> aboveMa, ReadOnlySpan<bool> onBuySignal, long timestamp)
|
|
{
|
|
if (volume.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newHigh.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newLow.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (aboveMa.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (onBuySignal.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* changePtr = change)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (bool* newHighPtr = newHigh)
|
|
fixed (bool* newLowPtr = newLow)
|
|
fixed (bool* aboveMaPtr = aboveMa)
|
|
fixed (bool* onBuySignalPtr = onBuySignal)
|
|
{
|
|
result = NativeMethods.wickra_breadth_thrust_update(_handle.DangerousGetHandle(), changePtr, volumePtr, newHighPtr, newLowPtr, aboveMaPtr, onBuySignalPtr, (nuint)change.Length, timestamp);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_breadth_thrust_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_breadth_thrust_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_breadth_thrust_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_breadth_thrust_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Breakaway : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Breakaway()
|
|
{
|
|
var ptr = NativeMethods.wickra_breakaway_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Breakaway parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_breakaway_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_breakaway_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_breakaway_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_breakaway_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_breakaway_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_breakaway_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_breakaway_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class BullishPercentIndex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public BullishPercentIndex()
|
|
{
|
|
var ptr = NativeMethods.wickra_bullish_percent_index_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid BullishPercentIndex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_bullish_percent_index_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> change, ReadOnlySpan<double> volume, ReadOnlySpan<bool> newHigh, ReadOnlySpan<bool> newLow, ReadOnlySpan<bool> aboveMa, ReadOnlySpan<bool> onBuySignal, long timestamp)
|
|
{
|
|
if (volume.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newHigh.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newLow.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (aboveMa.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (onBuySignal.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* changePtr = change)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (bool* newHighPtr = newHigh)
|
|
fixed (bool* newLowPtr = newLow)
|
|
fixed (bool* aboveMaPtr = aboveMa)
|
|
fixed (bool* onBuySignalPtr = onBuySignal)
|
|
{
|
|
result = NativeMethods.wickra_bullish_percent_index_update(_handle.DangerousGetHandle(), changePtr, volumePtr, newHighPtr, newLowPtr, aboveMaPtr, onBuySignalPtr, (nuint)change.Length, timestamp);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_bullish_percent_index_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_bullish_percent_index_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_bullish_percent_index_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_bullish_percent_index_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class BurkeRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public BurkeRatio(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_burke_ratio_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid BurkeRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_burke_ratio_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_burke_ratio_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_burke_ratio_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_burke_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_burke_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_burke_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_burke_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Butterfly : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Butterfly()
|
|
{
|
|
var ptr = NativeMethods.wickra_butterfly_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Butterfly parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_butterfly_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_butterfly_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_butterfly_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_butterfly_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_butterfly_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_butterfly_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_butterfly_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class CalendarSpread : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public CalendarSpread()
|
|
{
|
|
var ptr = NativeMethods.wickra_calendar_spread_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid CalendarSpread parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_calendar_spread_free);
|
|
}
|
|
|
|
public double Update(double fundingRate, double markPrice, double indexPrice, double futuresPrice, double openInterest, double longSize, double shortSize, double takerBuyVolume, double takerSellVolume, double longLiquidation, double shortLiquidation, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_calendar_spread_update(_handle.DangerousGetHandle(), fundingRate, markPrice, indexPrice, futuresPrice, openInterest, longSize, shortSize, takerBuyVolume, takerSellVolume, longLiquidation, shortLiquidation, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_calendar_spread_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_calendar_spread_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_calendar_spread_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_calendar_spread_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class CalmarRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public CalmarRatio(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_calmar_ratio_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid CalmarRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_calmar_ratio_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_calmar_ratio_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_calmar_ratio_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_calmar_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_calmar_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_calmar_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_calmar_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Camarilla : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Camarilla()
|
|
{
|
|
var ptr = NativeMethods.wickra_camarilla_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Camarilla parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_camarilla_free);
|
|
}
|
|
|
|
public CamarillaPivotsOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraCamarillaPivotsOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_camarilla_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new CamarillaPivotsOutput(native.pp, native.r1, native.r2, native.r3, native.r4, native.s1, native.s2, native.s3, native.s4) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_camarilla_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_camarilla_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_camarilla_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_camarilla_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class CandleReader : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
/// <summary>Parse a timestamp,open,high,low,close,volume CSV string (a
|
|
/// leading UTF-8 BOM and field whitespace are tolerated).</summary>
|
|
public CandleReader(string csv)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(csv);
|
|
var bytes = System.Text.Encoding.UTF8.GetBytes(csv);
|
|
nint ptr;
|
|
unsafe
|
|
{
|
|
fixed (byte* data = bytes)
|
|
{
|
|
ptr = NativeMethods.wickra_candle_reader_new(data, (nuint)bytes.Length);
|
|
}
|
|
}
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid CandleReader CSV");
|
|
}
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_candle_reader_free);
|
|
}
|
|
|
|
/// <summary>Every candle parsed from the CSV, in file order.</summary>
|
|
public Candle[] Read()
|
|
{
|
|
var count = (long)NativeMethods.wickra_candle_reader_count(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
if (count <= 0)
|
|
{
|
|
return Array.Empty<Candle>();
|
|
}
|
|
var buffer = new WickraCandle[count];
|
|
unsafe
|
|
{
|
|
fixed (WickraCandle* ptr = buffer)
|
|
{
|
|
NativeMethods.wickra_candle_reader_read(_handle.DangerousGetHandle(), ptr, (nuint)count);
|
|
}
|
|
}
|
|
GC.KeepAlive(_handle);
|
|
var result = new Candle[count];
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
result[i] = new Candle(buffer[i].open, buffer[i].high, buffer[i].low, buffer[i].close, buffer[i].volume, buffer[i].timestamp);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class CandleVolume : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public CandleVolume(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_candle_volume_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid CandleVolume parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_candle_volume_free);
|
|
}
|
|
|
|
public CandleVolumeOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraCandleVolumeOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_candle_volume_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new CandleVolumeOutput(native.body, native.width) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_candle_volume_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_candle_volume_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_candle_volume_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_candle_volume_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Cci : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Cci(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_cci_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Cci parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_cci_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_cci_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_cci_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_cci_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_cci_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_cci_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_cci_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class CenterOfGravity : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public CenterOfGravity(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_center_of_gravity_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid CenterOfGravity parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_center_of_gravity_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_center_of_gravity_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_center_of_gravity_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_center_of_gravity_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_center_of_gravity_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_center_of_gravity_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_center_of_gravity_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class CentralPivotRange : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public CentralPivotRange()
|
|
{
|
|
var ptr = NativeMethods.wickra_central_pivot_range_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid CentralPivotRange parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_central_pivot_range_free);
|
|
}
|
|
|
|
public CentralPivotRangeOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraCentralPivotRangeOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_central_pivot_range_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new CentralPivotRangeOutput(native.pivot, native.tc, native.bc) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_central_pivot_range_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_central_pivot_range_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_central_pivot_range_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_central_pivot_range_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Cfo : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Cfo(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_cfo_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Cfo parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_cfo_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_cfo_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_cfo_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_cfo_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_cfo_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_cfo_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_cfo_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ChaikinMoneyFlow : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ChaikinMoneyFlow(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_chaikin_money_flow_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ChaikinMoneyFlow parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_chaikin_money_flow_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_chaikin_money_flow_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_chaikin_money_flow_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_chaikin_money_flow_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_chaikin_money_flow_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_chaikin_money_flow_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_chaikin_money_flow_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ChaikinOscillator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ChaikinOscillator(int fast, int slow)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(fast);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(slow);
|
|
var ptr = NativeMethods.wickra_chaikin_oscillator_new((nuint)fast, (nuint)slow);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ChaikinOscillator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_chaikin_oscillator_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_chaikin_oscillator_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_chaikin_oscillator_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_chaikin_oscillator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_chaikin_oscillator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_chaikin_oscillator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_chaikin_oscillator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ChaikinVolatility : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ChaikinVolatility(int emaPeriod, int rocPeriod)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(emaPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(rocPeriod);
|
|
var ptr = NativeMethods.wickra_chaikin_volatility_new((nuint)emaPeriod, (nuint)rocPeriod);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ChaikinVolatility parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_chaikin_volatility_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_chaikin_volatility_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_chaikin_volatility_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_chaikin_volatility_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_chaikin_volatility_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_chaikin_volatility_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_chaikin_volatility_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ChandeKrollStop : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ChandeKrollStop(int atrPeriod, double atrMultiplier, int stopPeriod)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(atrPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(stopPeriod);
|
|
var ptr = NativeMethods.wickra_chande_kroll_stop_new((nuint)atrPeriod, atrMultiplier, (nuint)stopPeriod);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ChandeKrollStop parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_chande_kroll_stop_free);
|
|
}
|
|
|
|
public ChandeKrollStopOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraChandeKrollStopOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_chande_kroll_stop_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new ChandeKrollStopOutput(native.stop_long, native.stop_short) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_chande_kroll_stop_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_chande_kroll_stop_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_chande_kroll_stop_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_chande_kroll_stop_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ChandelierExit : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ChandelierExit(int period, double multiplier)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_chandelier_exit_new((nuint)period, multiplier);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ChandelierExit parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_chandelier_exit_free);
|
|
}
|
|
|
|
public ChandelierExitOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraChandelierExitOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_chandelier_exit_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new ChandelierExitOutput(native.long_stop, native.short_stop) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_chandelier_exit_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_chandelier_exit_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_chandelier_exit_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_chandelier_exit_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ChoppinessIndex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ChoppinessIndex(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_choppiness_index_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ChoppinessIndex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_choppiness_index_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_choppiness_index_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_choppiness_index_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_choppiness_index_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_choppiness_index_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_choppiness_index_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_choppiness_index_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ClassicPivots : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ClassicPivots()
|
|
{
|
|
var ptr = NativeMethods.wickra_classic_pivots_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ClassicPivots parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_classic_pivots_free);
|
|
}
|
|
|
|
public ClassicPivotsOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraClassicPivotsOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_classic_pivots_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new ClassicPivotsOutput(native.pp, native.r1, native.r2, native.r3, native.s1, native.s2, native.s3) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_classic_pivots_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_classic_pivots_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_classic_pivots_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_classic_pivots_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class CloseVsOpen : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public CloseVsOpen()
|
|
{
|
|
var ptr = NativeMethods.wickra_close_vs_open_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid CloseVsOpen parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_close_vs_open_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_close_vs_open_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_close_vs_open_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_close_vs_open_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_close_vs_open_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_close_vs_open_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_close_vs_open_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ClosingMarubozu : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ClosingMarubozu()
|
|
{
|
|
var ptr = NativeMethods.wickra_closing_marubozu_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ClosingMarubozu parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_closing_marubozu_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_closing_marubozu_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_closing_marubozu_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_closing_marubozu_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_closing_marubozu_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_closing_marubozu_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_closing_marubozu_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Cmo : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Cmo(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_cmo_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Cmo parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_cmo_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_cmo_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_cmo_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_cmo_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_cmo_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_cmo_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_cmo_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class CoefficientOfVariation : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public CoefficientOfVariation(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_coefficient_of_variation_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid CoefficientOfVariation parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_coefficient_of_variation_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_coefficient_of_variation_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_coefficient_of_variation_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_coefficient_of_variation_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_coefficient_of_variation_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_coefficient_of_variation_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_coefficient_of_variation_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Cointegration : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Cointegration(int period, int adfLags)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(adfLags);
|
|
var ptr = NativeMethods.wickra_cointegration_new((nuint)period, (nuint)adfLags);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Cointegration parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_cointegration_free);
|
|
}
|
|
|
|
public CointegrationOutput? Update(double x, double y)
|
|
{
|
|
WickraCointegrationOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_cointegration_update(_handle.DangerousGetHandle(), x, y, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new CointegrationOutput(native.hedge_ratio, native.spread, native.adf_stat) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_cointegration_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_cointegration_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_cointegration_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_cointegration_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class CommonSenseRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public CommonSenseRatio(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_common_sense_ratio_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid CommonSenseRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_common_sense_ratio_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_common_sense_ratio_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_common_sense_ratio_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_common_sense_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_common_sense_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_common_sense_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_common_sense_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class CompositeProfile : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public CompositeProfile(int period, int bins, double valueAreaPct)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(bins);
|
|
var ptr = NativeMethods.wickra_composite_profile_new((nuint)period, (nuint)bins, valueAreaPct);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid CompositeProfile parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_composite_profile_free);
|
|
}
|
|
|
|
public CompositeProfileOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraCompositeProfileOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_composite_profile_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new CompositeProfileOutput(native.poc, native.vah, native.val) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_composite_profile_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_composite_profile_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_composite_profile_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_composite_profile_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ConcealingBabySwallow : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ConcealingBabySwallow()
|
|
{
|
|
var ptr = NativeMethods.wickra_concealing_baby_swallow_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ConcealingBabySwallow parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_concealing_baby_swallow_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_concealing_baby_swallow_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_concealing_baby_swallow_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_concealing_baby_swallow_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_concealing_baby_swallow_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_concealing_baby_swallow_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_concealing_baby_swallow_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ConditionalValueAtRisk : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ConditionalValueAtRisk(int period, double confidence)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_conditional_value_at_risk_new((nuint)period, confidence);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ConditionalValueAtRisk parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_conditional_value_at_risk_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_conditional_value_at_risk_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_conditional_value_at_risk_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_conditional_value_at_risk_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_conditional_value_at_risk_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_conditional_value_at_risk_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_conditional_value_at_risk_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ConnorsRsi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ConnorsRsi(int periodRsi, int periodStreak, int periodRank)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(periodRsi);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(periodStreak);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(periodRank);
|
|
var ptr = NativeMethods.wickra_connors_rsi_new((nuint)periodRsi, (nuint)periodStreak, (nuint)periodRank);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ConnorsRsi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_connors_rsi_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_connors_rsi_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_connors_rsi_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_connors_rsi_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_connors_rsi_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_connors_rsi_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_connors_rsi_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Coppock : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Coppock(int rocLongPeriod, int rocShortPeriod, int wmaPeriod)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(rocLongPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(rocShortPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(wmaPeriod);
|
|
var ptr = NativeMethods.wickra_coppock_new((nuint)rocLongPeriod, (nuint)rocShortPeriod, (nuint)wmaPeriod);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Coppock parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_coppock_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_coppock_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_coppock_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_coppock_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_coppock_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_coppock_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_coppock_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class CorrelationTrendIndicator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public CorrelationTrendIndicator(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_correlation_trend_indicator_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid CorrelationTrendIndicator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_correlation_trend_indicator_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_correlation_trend_indicator_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_correlation_trend_indicator_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_correlation_trend_indicator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_correlation_trend_indicator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_correlation_trend_indicator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_correlation_trend_indicator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Counterattack : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Counterattack()
|
|
{
|
|
var ptr = NativeMethods.wickra_counterattack_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Counterattack parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_counterattack_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_counterattack_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_counterattack_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_counterattack_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_counterattack_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_counterattack_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_counterattack_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Crab : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Crab()
|
|
{
|
|
var ptr = NativeMethods.wickra_crab_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Crab parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_crab_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_crab_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_crab_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_crab_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_crab_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_crab_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_crab_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class CumulativeVolumeDelta : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public CumulativeVolumeDelta()
|
|
{
|
|
var ptr = NativeMethods.wickra_cumulative_volume_delta_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid CumulativeVolumeDelta parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_cumulative_volume_delta_free);
|
|
}
|
|
|
|
public double Update(double price, double size, bool isBuy, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_cumulative_volume_delta_update(_handle.DangerousGetHandle(), price, size, isBuy, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_cumulative_volume_delta_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_cumulative_volume_delta_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_cumulative_volume_delta_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_cumulative_volume_delta_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class CumulativeVolumeIndex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public CumulativeVolumeIndex()
|
|
{
|
|
var ptr = NativeMethods.wickra_cumulative_volume_index_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid CumulativeVolumeIndex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_cumulative_volume_index_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> change, ReadOnlySpan<double> volume, ReadOnlySpan<bool> newHigh, ReadOnlySpan<bool> newLow, ReadOnlySpan<bool> aboveMa, ReadOnlySpan<bool> onBuySignal, long timestamp)
|
|
{
|
|
if (volume.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newHigh.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newLow.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (aboveMa.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (onBuySignal.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* changePtr = change)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (bool* newHighPtr = newHigh)
|
|
fixed (bool* newLowPtr = newLow)
|
|
fixed (bool* aboveMaPtr = aboveMa)
|
|
fixed (bool* onBuySignalPtr = onBuySignal)
|
|
{
|
|
result = NativeMethods.wickra_cumulative_volume_index_update(_handle.DangerousGetHandle(), changePtr, volumePtr, newHighPtr, newLowPtr, aboveMaPtr, onBuySignalPtr, (nuint)change.Length, timestamp);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_cumulative_volume_index_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_cumulative_volume_index_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_cumulative_volume_index_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_cumulative_volume_index_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class CupAndHandle : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public CupAndHandle()
|
|
{
|
|
var ptr = NativeMethods.wickra_cup_and_handle_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid CupAndHandle parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_cup_and_handle_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_cup_and_handle_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_cup_and_handle_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_cup_and_handle_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_cup_and_handle_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_cup_and_handle_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_cup_and_handle_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class CyberneticCycle : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public CyberneticCycle(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_cybernetic_cycle_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid CyberneticCycle parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_cybernetic_cycle_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_cybernetic_cycle_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_cybernetic_cycle_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_cybernetic_cycle_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_cybernetic_cycle_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_cybernetic_cycle_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_cybernetic_cycle_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Cypher : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Cypher()
|
|
{
|
|
var ptr = NativeMethods.wickra_cypher_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Cypher parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_cypher_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_cypher_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_cypher_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_cypher_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_cypher_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_cypher_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_cypher_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class DayOfWeekProfile : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
private readonly int _valuesCapacity;
|
|
|
|
public DayOfWeekProfile(int utcOffsetMinutes)
|
|
{
|
|
var ptr = NativeMethods.wickra_day_of_week_profile_new(utcOffsetMinutes);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid DayOfWeekProfile parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_day_of_week_profile_free);
|
|
_valuesCapacity = 4096;
|
|
}
|
|
|
|
public double[]? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var values = new double[_valuesCapacity];
|
|
long length;
|
|
unsafe
|
|
{
|
|
fixed (double* valuesPtr = values)
|
|
{
|
|
length = (long)NativeMethods.wickra_day_of_week_profile_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, valuesPtr, (nuint)_valuesCapacity);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
if (length < 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (length < values.Length)
|
|
{
|
|
Array.Resize(ref values, (int)length);
|
|
}
|
|
|
|
return values;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_day_of_week_profile_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_day_of_week_profile_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_day_of_week_profile_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_day_of_week_profile_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Decycler : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Decycler(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_decycler_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Decycler parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_decycler_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_decycler_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_decycler_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_decycler_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_decycler_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_decycler_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_decycler_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class DecyclerOscillator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public DecyclerOscillator(int fast, int slow)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(fast);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(slow);
|
|
var ptr = NativeMethods.wickra_decycler_oscillator_new((nuint)fast, (nuint)slow);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid DecyclerOscillator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_decycler_oscillator_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_decycler_oscillator_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_decycler_oscillator_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_decycler_oscillator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_decycler_oscillator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_decycler_oscillator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_decycler_oscillator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Dema : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Dema(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_dema_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Dema parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_dema_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_dema_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_dema_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_dema_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_dema_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_dema_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_dema_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class DemandIndex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public DemandIndex(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_demand_index_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid DemandIndex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_demand_index_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_demand_index_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_demand_index_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_demand_index_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_demand_index_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_demand_index_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_demand_index_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class DemarkPivots : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public DemarkPivots()
|
|
{
|
|
var ptr = NativeMethods.wickra_demark_pivots_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid DemarkPivots parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_demark_pivots_free);
|
|
}
|
|
|
|
public DemarkPivotsOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraDemarkPivotsOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_demark_pivots_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new DemarkPivotsOutput(native.pp, native.r1, native.s1) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_demark_pivots_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_demark_pivots_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_demark_pivots_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_demark_pivots_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class DepthSlope : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public DepthSlope()
|
|
{
|
|
var ptr = NativeMethods.wickra_depth_slope_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid DepthSlope parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_depth_slope_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> bidPrice, ReadOnlySpan<double> bidSize, ReadOnlySpan<double> askPrice, ReadOnlySpan<double> askSize)
|
|
{
|
|
if (bidSize.Length != bidPrice.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (askSize.Length != askPrice.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* bidPricePtr = bidPrice)
|
|
fixed (double* bidSizePtr = bidSize)
|
|
fixed (double* askPricePtr = askPrice)
|
|
fixed (double* askSizePtr = askSize)
|
|
{
|
|
result = NativeMethods.wickra_depth_slope_update(_handle.DangerousGetHandle(), bidPricePtr, bidSizePtr, (nuint)bidPrice.Length, askPricePtr, askSizePtr, (nuint)askPrice.Length);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_depth_slope_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_depth_slope_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_depth_slope_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_depth_slope_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class DerivativeOscillator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public DerivativeOscillator(int rsiPeriod, int smooth1, int smooth2, int signalPeriod)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(rsiPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(smooth1);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(smooth2);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(signalPeriod);
|
|
var ptr = NativeMethods.wickra_derivative_oscillator_new((nuint)rsiPeriod, (nuint)smooth1, (nuint)smooth2, (nuint)signalPeriod);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid DerivativeOscillator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_derivative_oscillator_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_derivative_oscillator_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_derivative_oscillator_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_derivative_oscillator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_derivative_oscillator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_derivative_oscillator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_derivative_oscillator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class DetrendedStdDev : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public DetrendedStdDev(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_detrended_std_dev_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid DetrendedStdDev parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_detrended_std_dev_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_detrended_std_dev_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_detrended_std_dev_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_detrended_std_dev_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_detrended_std_dev_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_detrended_std_dev_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_detrended_std_dev_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class DisparityIndex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public DisparityIndex(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_disparity_index_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid DisparityIndex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_disparity_index_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_disparity_index_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_disparity_index_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_disparity_index_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_disparity_index_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_disparity_index_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_disparity_index_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class DistanceSsd : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public DistanceSsd(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_distance_ssd_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid DistanceSsd parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_distance_ssd_free);
|
|
}
|
|
|
|
public double Update(double x, double y)
|
|
{
|
|
var result = NativeMethods.wickra_distance_ssd_update(_handle.DangerousGetHandle(), x, y);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> x, ReadOnlySpan<double> y)
|
|
{
|
|
var n = x.Length;
|
|
if (y.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* xPtr = x)
|
|
fixed (double* yPtr = y)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_distance_ssd_batch(_handle.DangerousGetHandle(), xPtr, yPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_distance_ssd_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_distance_ssd_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_distance_ssd_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_distance_ssd_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Doji : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Doji()
|
|
{
|
|
var ptr = NativeMethods.wickra_doji_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Doji parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_doji_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_doji_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_doji_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_doji_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_doji_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_doji_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_doji_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class DojiStar : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public DojiStar()
|
|
{
|
|
var ptr = NativeMethods.wickra_doji_star_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid DojiStar parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_doji_star_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_doji_star_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_doji_star_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_doji_star_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_doji_star_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_doji_star_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_doji_star_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class DollarBars : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public DollarBars(double dollarPerBar)
|
|
{
|
|
var ptr = NativeMethods.wickra_dollar_bars_new(dollarPerBar);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid DollarBars parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_dollar_bars_free);
|
|
}
|
|
|
|
public DollarBar[] Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
const int cap = 64;
|
|
Span<WickraDollarBar> buffer = stackalloc WickraDollarBar[cap];
|
|
long count;
|
|
unsafe
|
|
{
|
|
fixed (WickraDollarBar* ptr = buffer)
|
|
{
|
|
count = (long)NativeMethods.wickra_dollar_bars_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, ptr, (nuint)cap);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
if (count <= 0)
|
|
{
|
|
return Array.Empty<DollarBar>();
|
|
}
|
|
|
|
var result = new DollarBar[count];
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
result[i] = new DollarBar(buffer[i].open, buffer[i].high, buffer[i].low, buffer[i].close, buffer[i].volume, buffer[i].dollar);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_dollar_bars_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_dollar_bars_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Donchian : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Donchian(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_donchian_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Donchian parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_donchian_free);
|
|
}
|
|
|
|
public DonchianOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraDonchianOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_donchian_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new DonchianOutput(native.upper, native.middle, native.lower) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_donchian_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_donchian_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_donchian_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_donchian_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class DonchianStop : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public DonchianStop(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_donchian_stop_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid DonchianStop parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_donchian_stop_free);
|
|
}
|
|
|
|
public DonchianStopOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraDonchianStopOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_donchian_stop_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new DonchianStopOutput(native.stop_long, native.stop_short) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_donchian_stop_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_donchian_stop_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_donchian_stop_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_donchian_stop_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class DoubleBollinger : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public DoubleBollinger(int period, double kInner, double kOuter)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_double_bollinger_new((nuint)period, kInner, kOuter);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid DoubleBollinger parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_double_bollinger_free);
|
|
}
|
|
|
|
public DoubleBollingerOutput? Update(double @value)
|
|
{
|
|
WickraDoubleBollingerOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_double_bollinger_update(_handle.DangerousGetHandle(), @value, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new DoubleBollingerOutput(native.upper_outer, native.upper_inner, native.middle, native.lower_inner, native.lower_outer) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_double_bollinger_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_double_bollinger_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_double_bollinger_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_double_bollinger_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class DoubleTopBottom : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public DoubleTopBottom()
|
|
{
|
|
var ptr = NativeMethods.wickra_double_top_bottom_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid DoubleTopBottom parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_double_top_bottom_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_double_top_bottom_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_double_top_bottom_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_double_top_bottom_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_double_top_bottom_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_double_top_bottom_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_double_top_bottom_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class DownsideGapThreeMethods : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public DownsideGapThreeMethods()
|
|
{
|
|
var ptr = NativeMethods.wickra_downside_gap_three_methods_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid DownsideGapThreeMethods parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_downside_gap_three_methods_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_downside_gap_three_methods_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_downside_gap_three_methods_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_downside_gap_three_methods_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_downside_gap_three_methods_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_downside_gap_three_methods_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_downside_gap_three_methods_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Dpo : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Dpo(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_dpo_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Dpo parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_dpo_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_dpo_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_dpo_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_dpo_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_dpo_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_dpo_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_dpo_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class DragonflyDoji : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public DragonflyDoji()
|
|
{
|
|
var ptr = NativeMethods.wickra_dragonfly_doji_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid DragonflyDoji parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_dragonfly_doji_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_dragonfly_doji_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_dragonfly_doji_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_dragonfly_doji_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_dragonfly_doji_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_dragonfly_doji_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_dragonfly_doji_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class DrawdownDuration : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public DrawdownDuration()
|
|
{
|
|
var ptr = NativeMethods.wickra_drawdown_duration_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid DrawdownDuration parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_drawdown_duration_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_drawdown_duration_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_drawdown_duration_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_drawdown_duration_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_drawdown_duration_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_drawdown_duration_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_drawdown_duration_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class DumplingTop : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public DumplingTop(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_dumpling_top_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid DumplingTop parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_dumpling_top_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_dumpling_top_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_dumpling_top_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_dumpling_top_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_dumpling_top_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_dumpling_top_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_dumpling_top_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Dx : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Dx(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_dx_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Dx parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_dx_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_dx_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_dx_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_dx_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_dx_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_dx_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_dx_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class DynamicMomentumIndex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public DynamicMomentumIndex(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_dynamic_momentum_index_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid DynamicMomentumIndex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_dynamic_momentum_index_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_dynamic_momentum_index_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_dynamic_momentum_index_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_dynamic_momentum_index_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_dynamic_momentum_index_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_dynamic_momentum_index_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_dynamic_momentum_index_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class EaseOfMovement : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public EaseOfMovement(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_ease_of_movement_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid EaseOfMovement parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ease_of_movement_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_ease_of_movement_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_ease_of_movement_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ease_of_movement_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ease_of_movement_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ease_of_movement_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ease_of_movement_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class EffectiveSpread : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public EffectiveSpread()
|
|
{
|
|
var ptr = NativeMethods.wickra_effective_spread_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid EffectiveSpread parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_effective_spread_free);
|
|
}
|
|
|
|
public double Update(double price, double size, bool isBuy, long timestamp, double mid)
|
|
{
|
|
var result = NativeMethods.wickra_effective_spread_update(_handle.DangerousGetHandle(), price, size, isBuy, timestamp, mid);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_effective_spread_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_effective_spread_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_effective_spread_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_effective_spread_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class EhlersStochastic : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public EhlersStochastic(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_ehlers_stochastic_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid EhlersStochastic parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ehlers_stochastic_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_ehlers_stochastic_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_ehlers_stochastic_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ehlers_stochastic_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ehlers_stochastic_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ehlers_stochastic_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ehlers_stochastic_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Ehma : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Ehma(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_ehma_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Ehma parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ehma_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_ehma_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_ehma_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ehma_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ehma_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ehma_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ehma_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ElderImpulse : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ElderImpulse(int emaPeriod, int macdFast, int macdSlow, int macdSignal)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(emaPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(macdFast);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(macdSlow);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(macdSignal);
|
|
var ptr = NativeMethods.wickra_elder_impulse_new((nuint)emaPeriod, (nuint)macdFast, (nuint)macdSlow, (nuint)macdSignal);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ElderImpulse parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_elder_impulse_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_elder_impulse_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_elder_impulse_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_elder_impulse_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_elder_impulse_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_elder_impulse_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_elder_impulse_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ElderRay : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ElderRay(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_elder_ray_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ElderRay parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_elder_ray_free);
|
|
}
|
|
|
|
public ElderRayOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraElderRayOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_elder_ray_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new ElderRayOutput(native.bull_power, native.bear_power) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_elder_ray_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_elder_ray_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_elder_ray_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_elder_ray_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ElderSafeZone : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ElderSafeZone(int period, double coeff)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_elder_safe_zone_new((nuint)period, coeff);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ElderSafeZone parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_elder_safe_zone_free);
|
|
}
|
|
|
|
public ElderSafeZoneOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraElderSafeZoneOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_elder_safe_zone_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new ElderSafeZoneOutput(native.@value, native.direction) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_elder_safe_zone_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_elder_safe_zone_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_elder_safe_zone_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_elder_safe_zone_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Ema : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Ema(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_ema_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Ema parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ema_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_ema_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_ema_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ema_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ema_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ema_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ema_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class EmpiricalModeDecomposition : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public EmpiricalModeDecomposition(int period, double fraction)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_empirical_mode_decomposition_new((nuint)period, fraction);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid EmpiricalModeDecomposition parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_empirical_mode_decomposition_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_empirical_mode_decomposition_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_empirical_mode_decomposition_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_empirical_mode_decomposition_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_empirical_mode_decomposition_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_empirical_mode_decomposition_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_empirical_mode_decomposition_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Engulfing : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Engulfing()
|
|
{
|
|
var ptr = NativeMethods.wickra_engulfing_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Engulfing parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_engulfing_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_engulfing_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_engulfing_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_engulfing_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_engulfing_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_engulfing_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_engulfing_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Equivolume : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Equivolume(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_equivolume_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Equivolume parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_equivolume_free);
|
|
}
|
|
|
|
public EquivolumeOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraEquivolumeOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_equivolume_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new EquivolumeOutput(native.height, native.width) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_equivolume_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_equivolume_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_equivolume_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_equivolume_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class EstimatedLeverageRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public EstimatedLeverageRatio()
|
|
{
|
|
var ptr = NativeMethods.wickra_estimated_leverage_ratio_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid EstimatedLeverageRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_estimated_leverage_ratio_free);
|
|
}
|
|
|
|
public double Update(double fundingRate, double markPrice, double indexPrice, double futuresPrice, double openInterest, double longSize, double shortSize, double takerBuyVolume, double takerSellVolume, double longLiquidation, double shortLiquidation, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_estimated_leverage_ratio_update(_handle.DangerousGetHandle(), fundingRate, markPrice, indexPrice, futuresPrice, openInterest, longSize, shortSize, takerBuyVolume, takerSellVolume, longLiquidation, shortLiquidation, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_estimated_leverage_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_estimated_leverage_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_estimated_leverage_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_estimated_leverage_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class EvenBetterSinewave : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public EvenBetterSinewave(int hpPeriod, int ssfLength)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(hpPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(ssfLength);
|
|
var ptr = NativeMethods.wickra_even_better_sinewave_new((nuint)hpPeriod, (nuint)ssfLength);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid EvenBetterSinewave parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_even_better_sinewave_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_even_better_sinewave_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_even_better_sinewave_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_even_better_sinewave_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_even_better_sinewave_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_even_better_sinewave_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_even_better_sinewave_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class EveningDojiStar : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public EveningDojiStar()
|
|
{
|
|
var ptr = NativeMethods.wickra_evening_doji_star_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid EveningDojiStar parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_evening_doji_star_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_evening_doji_star_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_evening_doji_star_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_evening_doji_star_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_evening_doji_star_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_evening_doji_star_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_evening_doji_star_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Evwma : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Evwma(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_evwma_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Evwma parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_evwma_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_evwma_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_evwma_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_evwma_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_evwma_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_evwma_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_evwma_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class EwmaVolatility : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public EwmaVolatility(double lambda)
|
|
{
|
|
var ptr = NativeMethods.wickra_ewma_volatility_new(lambda);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid EwmaVolatility parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ewma_volatility_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_ewma_volatility_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_ewma_volatility_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ewma_volatility_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ewma_volatility_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ewma_volatility_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ewma_volatility_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Expectancy : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Expectancy(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_expectancy_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Expectancy parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_expectancy_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_expectancy_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_expectancy_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_expectancy_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_expectancy_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_expectancy_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_expectancy_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FallingThreeMethods : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FallingThreeMethods()
|
|
{
|
|
var ptr = NativeMethods.wickra_falling_three_methods_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FallingThreeMethods parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_falling_three_methods_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_falling_three_methods_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_falling_three_methods_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_falling_three_methods_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_falling_three_methods_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_falling_three_methods_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_falling_three_methods_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Fama : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Fama(double fastLimit, double slowLimit)
|
|
{
|
|
var ptr = NativeMethods.wickra_fama_new(fastLimit, slowLimit);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Fama parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_fama_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_fama_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_fama_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_fama_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_fama_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_fama_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_fama_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FibArcs : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FibArcs()
|
|
{
|
|
var ptr = NativeMethods.wickra_fib_arcs_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FibArcs parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_fib_arcs_free);
|
|
}
|
|
|
|
public FibArcsOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraFibArcsOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_fib_arcs_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new FibArcsOutput(native.arc_382, native.arc_500, native.arc_618) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_fib_arcs_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_fib_arcs_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_fib_arcs_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_fib_arcs_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FibChannel : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FibChannel()
|
|
{
|
|
var ptr = NativeMethods.wickra_fib_channel_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FibChannel parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_fib_channel_free);
|
|
}
|
|
|
|
public FibChannelOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraFibChannelOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_fib_channel_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new FibChannelOutput(native.@base, native.level_618, native.level_1000, native.level_1618) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_fib_channel_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_fib_channel_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_fib_channel_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_fib_channel_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FibConfluence : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FibConfluence()
|
|
{
|
|
var ptr = NativeMethods.wickra_fib_confluence_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FibConfluence parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_fib_confluence_free);
|
|
}
|
|
|
|
public FibConfluenceOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraFibConfluenceOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_fib_confluence_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new FibConfluenceOutput(native.price, native.strength) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_fib_confluence_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_fib_confluence_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_fib_confluence_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_fib_confluence_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FibExtension : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FibExtension()
|
|
{
|
|
var ptr = NativeMethods.wickra_fib_extension_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FibExtension parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_fib_extension_free);
|
|
}
|
|
|
|
public FibExtensionOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraFibExtensionOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_fib_extension_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new FibExtensionOutput(native.level_1272, native.level_1414, native.level_1618, native.level_2000, native.level_2618) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_fib_extension_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_fib_extension_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_fib_extension_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_fib_extension_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FibFan : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FibFan()
|
|
{
|
|
var ptr = NativeMethods.wickra_fib_fan_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FibFan parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_fib_fan_free);
|
|
}
|
|
|
|
public FibFanOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraFibFanOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_fib_fan_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new FibFanOutput(native.fan_382, native.fan_500, native.fan_618) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_fib_fan_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_fib_fan_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_fib_fan_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_fib_fan_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FibProjection : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FibProjection()
|
|
{
|
|
var ptr = NativeMethods.wickra_fib_projection_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FibProjection parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_fib_projection_free);
|
|
}
|
|
|
|
public FibProjectionOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraFibProjectionOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_fib_projection_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new FibProjectionOutput(native.level_618, native.level_1000, native.level_1618, native.level_2618) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_fib_projection_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_fib_projection_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_fib_projection_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_fib_projection_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FibRetracement : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FibRetracement()
|
|
{
|
|
var ptr = NativeMethods.wickra_fib_retracement_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FibRetracement parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_fib_retracement_free);
|
|
}
|
|
|
|
public FibRetracementOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraFibRetracementOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_fib_retracement_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new FibRetracementOutput(native.level_0, native.level_236, native.level_382, native.level_500, native.level_618, native.level_786, native.level_1000) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_fib_retracement_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_fib_retracement_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_fib_retracement_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_fib_retracement_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FibTimeZones : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FibTimeZones()
|
|
{
|
|
var ptr = NativeMethods.wickra_fib_time_zones_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FibTimeZones parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_fib_time_zones_free);
|
|
}
|
|
|
|
public FibTimeZonesOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraFibTimeZonesOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_fib_time_zones_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new FibTimeZonesOutput(native.on_zone, native.bars_to_next) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_fib_time_zones_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_fib_time_zones_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_fib_time_zones_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_fib_time_zones_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FibonacciPivots : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FibonacciPivots()
|
|
{
|
|
var ptr = NativeMethods.wickra_fibonacci_pivots_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FibonacciPivots parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_fibonacci_pivots_free);
|
|
}
|
|
|
|
public FibonacciPivotsOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraFibonacciPivotsOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_fibonacci_pivots_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new FibonacciPivotsOutput(native.pp, native.r1, native.r2, native.r3, native.s1, native.s2, native.s3) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_fibonacci_pivots_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_fibonacci_pivots_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_fibonacci_pivots_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_fibonacci_pivots_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FisherRsi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FisherRsi(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_fisher_rsi_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FisherRsi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_fisher_rsi_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_fisher_rsi_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_fisher_rsi_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_fisher_rsi_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_fisher_rsi_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_fisher_rsi_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_fisher_rsi_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FisherTransform : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FisherTransform(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_fisher_transform_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FisherTransform parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_fisher_transform_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_fisher_transform_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_fisher_transform_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_fisher_transform_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_fisher_transform_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_fisher_transform_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_fisher_transform_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FlagPennant : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FlagPennant()
|
|
{
|
|
var ptr = NativeMethods.wickra_flag_pennant_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FlagPennant parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_flag_pennant_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_flag_pennant_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_flag_pennant_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_flag_pennant_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_flag_pennant_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_flag_pennant_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_flag_pennant_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Footprint : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Footprint(double tickSize)
|
|
{
|
|
var ptr = NativeMethods.wickra_footprint_new(tickSize);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Footprint parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_footprint_free);
|
|
}
|
|
|
|
public FootprintLevel[] Update(double price, double size, bool isBuy, long timestamp)
|
|
{
|
|
const int cap = 64;
|
|
Span<WickraFootprintLevel> buffer = stackalloc WickraFootprintLevel[cap];
|
|
long count;
|
|
unsafe
|
|
{
|
|
fixed (WickraFootprintLevel* ptr = buffer)
|
|
{
|
|
count = (long)NativeMethods.wickra_footprint_update(_handle.DangerousGetHandle(), price, size, isBuy, timestamp, ptr, (nuint)cap);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
if (count <= 0)
|
|
{
|
|
return Array.Empty<FootprintLevel>();
|
|
}
|
|
|
|
var result = new FootprintLevel[count];
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
result[i] = new FootprintLevel(buffer[i].price, buffer[i].bid_vol, buffer[i].ask_vol);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_footprint_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_footprint_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_footprint_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_footprint_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ForceIndex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ForceIndex(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_force_index_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ForceIndex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_force_index_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_force_index_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_force_index_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_force_index_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_force_index_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_force_index_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_force_index_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FractalChaosBands : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FractalChaosBands(int k)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(k);
|
|
var ptr = NativeMethods.wickra_fractal_chaos_bands_new((nuint)k);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FractalChaosBands parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_fractal_chaos_bands_free);
|
|
}
|
|
|
|
public FractalChaosBandsOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraFractalChaosBandsOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_fractal_chaos_bands_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new FractalChaosBandsOutput(native.upper, native.lower) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_fractal_chaos_bands_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_fractal_chaos_bands_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_fractal_chaos_bands_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_fractal_chaos_bands_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Frama : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Frama(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_frama_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Frama parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_frama_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_frama_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_frama_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_frama_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_frama_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_frama_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_frama_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FryPanBottom : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FryPanBottom(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_fry_pan_bottom_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FryPanBottom parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_fry_pan_bottom_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_fry_pan_bottom_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_fry_pan_bottom_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_fry_pan_bottom_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_fry_pan_bottom_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_fry_pan_bottom_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_fry_pan_bottom_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FundingBasis : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FundingBasis()
|
|
{
|
|
var ptr = NativeMethods.wickra_funding_basis_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FundingBasis parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_funding_basis_free);
|
|
}
|
|
|
|
public double Update(double fundingRate, double markPrice, double indexPrice, double futuresPrice, double openInterest, double longSize, double shortSize, double takerBuyVolume, double takerSellVolume, double longLiquidation, double shortLiquidation, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_funding_basis_update(_handle.DangerousGetHandle(), fundingRate, markPrice, indexPrice, futuresPrice, openInterest, longSize, shortSize, takerBuyVolume, takerSellVolume, longLiquidation, shortLiquidation, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_funding_basis_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_funding_basis_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_funding_basis_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_funding_basis_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FundingImpliedApr : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FundingImpliedApr(double intervalsPerYear)
|
|
{
|
|
var ptr = NativeMethods.wickra_funding_implied_apr_new(intervalsPerYear);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FundingImpliedApr parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_funding_implied_apr_free);
|
|
}
|
|
|
|
public double Update(double fundingRate, double markPrice, double indexPrice, double futuresPrice, double openInterest, double longSize, double shortSize, double takerBuyVolume, double takerSellVolume, double longLiquidation, double shortLiquidation, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_funding_implied_apr_update(_handle.DangerousGetHandle(), fundingRate, markPrice, indexPrice, futuresPrice, openInterest, longSize, shortSize, takerBuyVolume, takerSellVolume, longLiquidation, shortLiquidation, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_funding_implied_apr_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_funding_implied_apr_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_funding_implied_apr_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_funding_implied_apr_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FundingRate : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FundingRate()
|
|
{
|
|
var ptr = NativeMethods.wickra_funding_rate_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FundingRate parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_funding_rate_free);
|
|
}
|
|
|
|
public double Update(double fundingRate, double markPrice, double indexPrice, double futuresPrice, double openInterest, double longSize, double shortSize, double takerBuyVolume, double takerSellVolume, double longLiquidation, double shortLiquidation, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_funding_rate_update(_handle.DangerousGetHandle(), fundingRate, markPrice, indexPrice, futuresPrice, openInterest, longSize, shortSize, takerBuyVolume, takerSellVolume, longLiquidation, shortLiquidation, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_funding_rate_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_funding_rate_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_funding_rate_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_funding_rate_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FundingRateMean : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FundingRateMean(int window)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(window);
|
|
var ptr = NativeMethods.wickra_funding_rate_mean_new((nuint)window);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FundingRateMean parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_funding_rate_mean_free);
|
|
}
|
|
|
|
public double Update(double fundingRate, double markPrice, double indexPrice, double futuresPrice, double openInterest, double longSize, double shortSize, double takerBuyVolume, double takerSellVolume, double longLiquidation, double shortLiquidation, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_funding_rate_mean_update(_handle.DangerousGetHandle(), fundingRate, markPrice, indexPrice, futuresPrice, openInterest, longSize, shortSize, takerBuyVolume, takerSellVolume, longLiquidation, shortLiquidation, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_funding_rate_mean_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_funding_rate_mean_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_funding_rate_mean_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_funding_rate_mean_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class FundingRateZScore : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public FundingRateZScore(int window)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(window);
|
|
var ptr = NativeMethods.wickra_funding_rate_z_score_new((nuint)window);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid FundingRateZScore parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_funding_rate_z_score_free);
|
|
}
|
|
|
|
public double Update(double fundingRate, double markPrice, double indexPrice, double futuresPrice, double openInterest, double longSize, double shortSize, double takerBuyVolume, double takerSellVolume, double longLiquidation, double shortLiquidation, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_funding_rate_z_score_update(_handle.DangerousGetHandle(), fundingRate, markPrice, indexPrice, futuresPrice, openInterest, longSize, shortSize, takerBuyVolume, takerSellVolume, longLiquidation, shortLiquidation, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_funding_rate_z_score_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_funding_rate_z_score_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_funding_rate_z_score_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_funding_rate_z_score_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class GainLossRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public GainLossRatio(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_gain_loss_ratio_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid GainLossRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_gain_loss_ratio_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_gain_loss_ratio_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_gain_loss_ratio_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_gain_loss_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_gain_loss_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_gain_loss_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_gain_loss_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class GainToPainRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public GainToPainRatio(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_gain_to_pain_ratio_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid GainToPainRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_gain_to_pain_ratio_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_gain_to_pain_ratio_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_gain_to_pain_ratio_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_gain_to_pain_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_gain_to_pain_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_gain_to_pain_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_gain_to_pain_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class GapSideBySideWhite : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public GapSideBySideWhite()
|
|
{
|
|
var ptr = NativeMethods.wickra_gap_side_by_side_white_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid GapSideBySideWhite parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_gap_side_by_side_white_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_gap_side_by_side_white_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_gap_side_by_side_white_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_gap_side_by_side_white_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_gap_side_by_side_white_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_gap_side_by_side_white_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_gap_side_by_side_white_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Garch11 : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Garch11(double omega, double alpha, double beta)
|
|
{
|
|
var ptr = NativeMethods.wickra_garch11_new(omega, alpha, beta);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Garch11 parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_garch11_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_garch11_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_garch11_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_garch11_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_garch11_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_garch11_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_garch11_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class GarmanKlassVolatility : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public GarmanKlassVolatility(int period, int tradingPeriods)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(tradingPeriods);
|
|
var ptr = NativeMethods.wickra_garman_klass_volatility_new((nuint)period, (nuint)tradingPeriods);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid GarmanKlassVolatility parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_garman_klass_volatility_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_garman_klass_volatility_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_garman_klass_volatility_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_garman_klass_volatility_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_garman_klass_volatility_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_garman_klass_volatility_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_garman_klass_volatility_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Gartley : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Gartley()
|
|
{
|
|
var ptr = NativeMethods.wickra_gartley_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Gartley parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_gartley_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_gartley_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_gartley_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_gartley_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_gartley_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_gartley_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_gartley_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class GatorOscillator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public GatorOscillator(int jawPeriod, int teethPeriod, int lipsPeriod)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(jawPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(teethPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(lipsPeriod);
|
|
var ptr = NativeMethods.wickra_gator_oscillator_new((nuint)jawPeriod, (nuint)teethPeriod, (nuint)lipsPeriod);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid GatorOscillator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_gator_oscillator_free);
|
|
}
|
|
|
|
public GatorOscillatorOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraGatorOscillatorOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_gator_oscillator_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new GatorOscillatorOutput(native.upper, native.lower) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_gator_oscillator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_gator_oscillator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_gator_oscillator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_gator_oscillator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class GeneralizedDema : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public GeneralizedDema(int period, double v)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_generalized_dema_new((nuint)period, v);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid GeneralizedDema parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_generalized_dema_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_generalized_dema_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_generalized_dema_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_generalized_dema_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_generalized_dema_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_generalized_dema_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_generalized_dema_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class GeometricMa : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public GeometricMa(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_geometric_ma_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid GeometricMa parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_geometric_ma_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_geometric_ma_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_geometric_ma_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_geometric_ma_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_geometric_ma_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_geometric_ma_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_geometric_ma_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class GoldenPocket : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public GoldenPocket()
|
|
{
|
|
var ptr = NativeMethods.wickra_golden_pocket_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid GoldenPocket parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_golden_pocket_free);
|
|
}
|
|
|
|
public GoldenPocketOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraGoldenPocketOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_golden_pocket_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new GoldenPocketOutput(native.low, native.mid, native.high) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_golden_pocket_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_golden_pocket_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_golden_pocket_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_golden_pocket_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class GrangerCausality : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public GrangerCausality(int period, int lag)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(lag);
|
|
var ptr = NativeMethods.wickra_granger_causality_new((nuint)period, (nuint)lag);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid GrangerCausality parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_granger_causality_free);
|
|
}
|
|
|
|
public double Update(double x, double y)
|
|
{
|
|
var result = NativeMethods.wickra_granger_causality_update(_handle.DangerousGetHandle(), x, y);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> x, ReadOnlySpan<double> y)
|
|
{
|
|
var n = x.Length;
|
|
if (y.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* xPtr = x)
|
|
fixed (double* yPtr = y)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_granger_causality_batch(_handle.DangerousGetHandle(), xPtr, yPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_granger_causality_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_granger_causality_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_granger_causality_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_granger_causality_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class GravestoneDoji : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public GravestoneDoji()
|
|
{
|
|
var ptr = NativeMethods.wickra_gravestone_doji_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid GravestoneDoji parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_gravestone_doji_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_gravestone_doji_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_gravestone_doji_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_gravestone_doji_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_gravestone_doji_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_gravestone_doji_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_gravestone_doji_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Hammer : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Hammer()
|
|
{
|
|
var ptr = NativeMethods.wickra_hammer_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Hammer parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_hammer_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_hammer_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_hammer_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_hammer_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_hammer_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_hammer_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_hammer_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HangingMan : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HangingMan()
|
|
{
|
|
var ptr = NativeMethods.wickra_hanging_man_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HangingMan parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_hanging_man_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_hanging_man_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_hanging_man_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_hanging_man_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_hanging_man_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_hanging_man_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_hanging_man_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Harami : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Harami()
|
|
{
|
|
var ptr = NativeMethods.wickra_harami_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Harami parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_harami_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_harami_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_harami_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_harami_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_harami_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_harami_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_harami_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HaramiCross : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HaramiCross()
|
|
{
|
|
var ptr = NativeMethods.wickra_harami_cross_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HaramiCross parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_harami_cross_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_harami_cross_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_harami_cross_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_harami_cross_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_harami_cross_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_harami_cross_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_harami_cross_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HasbrouckInformationShare : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HasbrouckInformationShare(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_hasbrouck_information_share_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HasbrouckInformationShare parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_hasbrouck_information_share_free);
|
|
}
|
|
|
|
public double Update(double x, double y)
|
|
{
|
|
var result = NativeMethods.wickra_hasbrouck_information_share_update(_handle.DangerousGetHandle(), x, y);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> x, ReadOnlySpan<double> y)
|
|
{
|
|
var n = x.Length;
|
|
if (y.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* xPtr = x)
|
|
fixed (double* yPtr = y)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_hasbrouck_information_share_batch(_handle.DangerousGetHandle(), xPtr, yPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_hasbrouck_information_share_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_hasbrouck_information_share_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_hasbrouck_information_share_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_hasbrouck_information_share_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HeadAndShoulders : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HeadAndShoulders()
|
|
{
|
|
var ptr = NativeMethods.wickra_head_and_shoulders_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HeadAndShoulders parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_head_and_shoulders_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_head_and_shoulders_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_head_and_shoulders_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_head_and_shoulders_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_head_and_shoulders_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_head_and_shoulders_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_head_and_shoulders_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HeikinAshi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HeikinAshi()
|
|
{
|
|
var ptr = NativeMethods.wickra_heikin_ashi_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HeikinAshi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_heikin_ashi_free);
|
|
}
|
|
|
|
public HeikinAshiOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraHeikinAshiOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_heikin_ashi_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new HeikinAshiOutput(native.open, native.high, native.low, native.close) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_heikin_ashi_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_heikin_ashi_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_heikin_ashi_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_heikin_ashi_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HeikinAshiOscillator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HeikinAshiOscillator(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_heikin_ashi_oscillator_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HeikinAshiOscillator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_heikin_ashi_oscillator_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_heikin_ashi_oscillator_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_heikin_ashi_oscillator_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_heikin_ashi_oscillator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_heikin_ashi_oscillator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_heikin_ashi_oscillator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_heikin_ashi_oscillator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HiLoActivator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HiLoActivator(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_hi_lo_activator_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HiLoActivator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_hi_lo_activator_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_hi_lo_activator_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_hi_lo_activator_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_hi_lo_activator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_hi_lo_activator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_hi_lo_activator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_hi_lo_activator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HighLowIndex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HighLowIndex(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_high_low_index_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HighLowIndex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_high_low_index_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> change, ReadOnlySpan<double> volume, ReadOnlySpan<bool> newHigh, ReadOnlySpan<bool> newLow, ReadOnlySpan<bool> aboveMa, ReadOnlySpan<bool> onBuySignal, long timestamp)
|
|
{
|
|
if (volume.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newHigh.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newLow.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (aboveMa.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (onBuySignal.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* changePtr = change)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (bool* newHighPtr = newHigh)
|
|
fixed (bool* newLowPtr = newLow)
|
|
fixed (bool* aboveMaPtr = aboveMa)
|
|
fixed (bool* onBuySignalPtr = onBuySignal)
|
|
{
|
|
result = NativeMethods.wickra_high_low_index_update(_handle.DangerousGetHandle(), changePtr, volumePtr, newHighPtr, newLowPtr, aboveMaPtr, onBuySignalPtr, (nuint)change.Length, timestamp);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_high_low_index_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_high_low_index_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_high_low_index_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_high_low_index_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HighLowRange : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HighLowRange()
|
|
{
|
|
var ptr = NativeMethods.wickra_high_low_range_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HighLowRange parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_high_low_range_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_high_low_range_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_high_low_range_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_high_low_range_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_high_low_range_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_high_low_range_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_high_low_range_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HighLowVolumeNodes : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HighLowVolumeNodes(int period, int bins)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(bins);
|
|
var ptr = NativeMethods.wickra_high_low_volume_nodes_new((nuint)period, (nuint)bins);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HighLowVolumeNodes parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_high_low_volume_nodes_free);
|
|
}
|
|
|
|
public HighLowVolumeNodesOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraHighLowVolumeNodesOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_high_low_volume_nodes_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new HighLowVolumeNodesOutput(native.hvn, native.lvn) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_high_low_volume_nodes_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_high_low_volume_nodes_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_high_low_volume_nodes_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_high_low_volume_nodes_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HighWave : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HighWave()
|
|
{
|
|
var ptr = NativeMethods.wickra_high_wave_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HighWave parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_high_wave_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_high_wave_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_high_wave_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_high_wave_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_high_wave_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_high_wave_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_high_wave_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HighpassFilter : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HighpassFilter(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_highpass_filter_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HighpassFilter parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_highpass_filter_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_highpass_filter_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_highpass_filter_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_highpass_filter_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_highpass_filter_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_highpass_filter_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_highpass_filter_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Hikkake : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Hikkake()
|
|
{
|
|
var ptr = NativeMethods.wickra_hikkake_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Hikkake parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_hikkake_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_hikkake_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_hikkake_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_hikkake_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_hikkake_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_hikkake_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_hikkake_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HikkakeModified : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HikkakeModified()
|
|
{
|
|
var ptr = NativeMethods.wickra_hikkake_modified_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HikkakeModified parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_hikkake_modified_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_hikkake_modified_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_hikkake_modified_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_hikkake_modified_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_hikkake_modified_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_hikkake_modified_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_hikkake_modified_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HilbertDominantCycle : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HilbertDominantCycle()
|
|
{
|
|
var ptr = NativeMethods.wickra_hilbert_dominant_cycle_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HilbertDominantCycle parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_hilbert_dominant_cycle_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_hilbert_dominant_cycle_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_hilbert_dominant_cycle_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_hilbert_dominant_cycle_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_hilbert_dominant_cycle_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_hilbert_dominant_cycle_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_hilbert_dominant_cycle_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HistoricalVolatility : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HistoricalVolatility(int period, int tradingPeriods)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(tradingPeriods);
|
|
var ptr = NativeMethods.wickra_historical_volatility_new((nuint)period, (nuint)tradingPeriods);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HistoricalVolatility parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_historical_volatility_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_historical_volatility_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_historical_volatility_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_historical_volatility_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_historical_volatility_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_historical_volatility_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_historical_volatility_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Hma : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Hma(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_hma_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Hma parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_hma_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_hma_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_hma_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_hma_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_hma_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_hma_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_hma_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HoltWinters : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HoltWinters(double alpha, double beta)
|
|
{
|
|
var ptr = NativeMethods.wickra_holt_winters_new(alpha, beta);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HoltWinters parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_holt_winters_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_holt_winters_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_holt_winters_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_holt_winters_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_holt_winters_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_holt_winters_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_holt_winters_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HomingPigeon : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HomingPigeon()
|
|
{
|
|
var ptr = NativeMethods.wickra_homing_pigeon_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HomingPigeon parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_homing_pigeon_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_homing_pigeon_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_homing_pigeon_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_homing_pigeon_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_homing_pigeon_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_homing_pigeon_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_homing_pigeon_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HtDcPhase : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HtDcPhase()
|
|
{
|
|
var ptr = NativeMethods.wickra_ht_dc_phase_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HtDcPhase parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ht_dc_phase_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_ht_dc_phase_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_ht_dc_phase_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ht_dc_phase_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ht_dc_phase_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ht_dc_phase_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ht_dc_phase_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HtPhasor : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HtPhasor()
|
|
{
|
|
var ptr = NativeMethods.wickra_ht_phasor_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HtPhasor parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ht_phasor_free);
|
|
}
|
|
|
|
public HtPhasorOutput? Update(double @value)
|
|
{
|
|
WickraHtPhasorOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_ht_phasor_update(_handle.DangerousGetHandle(), @value, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new HtPhasorOutput(native.inphase, native.quadrature) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ht_phasor_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ht_phasor_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ht_phasor_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ht_phasor_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HtTrendMode : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HtTrendMode()
|
|
{
|
|
var ptr = NativeMethods.wickra_ht_trend_mode_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HtTrendMode parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ht_trend_mode_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_ht_trend_mode_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_ht_trend_mode_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ht_trend_mode_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ht_trend_mode_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ht_trend_mode_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ht_trend_mode_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HurstChannel : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HurstChannel(int period, double multiplier)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_hurst_channel_new((nuint)period, multiplier);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HurstChannel parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_hurst_channel_free);
|
|
}
|
|
|
|
public HurstChannelOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraHurstChannelOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_hurst_channel_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new HurstChannelOutput(native.upper, native.middle, native.lower) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_hurst_channel_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_hurst_channel_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_hurst_channel_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_hurst_channel_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class HurstExponent : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public HurstExponent(int period, int chunks)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(chunks);
|
|
var ptr = NativeMethods.wickra_hurst_exponent_new((nuint)period, (nuint)chunks);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid HurstExponent parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_hurst_exponent_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_hurst_exponent_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_hurst_exponent_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_hurst_exponent_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_hurst_exponent_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_hurst_exponent_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_hurst_exponent_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Ichimoku : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Ichimoku(int tenkanPeriod, int kijunPeriod, int senkouBPeriod, int displacement)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(tenkanPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(kijunPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(senkouBPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(displacement);
|
|
var ptr = NativeMethods.wickra_ichimoku_new((nuint)tenkanPeriod, (nuint)kijunPeriod, (nuint)senkouBPeriod, (nuint)displacement);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Ichimoku parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ichimoku_free);
|
|
}
|
|
|
|
public IchimokuOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraIchimokuOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_ichimoku_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new IchimokuOutput(native.tenkan, native.kijun, native.senkou_a, native.senkou_b, native.chikou) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ichimoku_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ichimoku_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ichimoku_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ichimoku_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class IdenticalThreeCrows : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public IdenticalThreeCrows()
|
|
{
|
|
var ptr = NativeMethods.wickra_identical_three_crows_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid IdenticalThreeCrows parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_identical_three_crows_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_identical_three_crows_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_identical_three_crows_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_identical_three_crows_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_identical_three_crows_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_identical_three_crows_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_identical_three_crows_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ImbalanceBars : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ImbalanceBars(double threshold)
|
|
{
|
|
var ptr = NativeMethods.wickra_imbalance_bars_new(threshold);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ImbalanceBars parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_imbalance_bars_free);
|
|
}
|
|
|
|
public ImbalanceBar[] Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
const int cap = 64;
|
|
Span<WickraImbalanceBar> buffer = stackalloc WickraImbalanceBar[cap];
|
|
long count;
|
|
unsafe
|
|
{
|
|
fixed (WickraImbalanceBar* ptr = buffer)
|
|
{
|
|
count = (long)NativeMethods.wickra_imbalance_bars_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, ptr, (nuint)cap);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
if (count <= 0)
|
|
{
|
|
return Array.Empty<ImbalanceBar>();
|
|
}
|
|
|
|
var result = new ImbalanceBar[count];
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
result[i] = new ImbalanceBar(buffer[i].open, buffer[i].high, buffer[i].low, buffer[i].close, buffer[i].imbalance, buffer[i].direction);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_imbalance_bars_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_imbalance_bars_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class InNeck : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public InNeck()
|
|
{
|
|
var ptr = NativeMethods.wickra_in_neck_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid InNeck parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_in_neck_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_in_neck_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_in_neck_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_in_neck_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_in_neck_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_in_neck_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_in_neck_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Inertia : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Inertia(int rviPeriod, int linregPeriod)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(rviPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(linregPeriod);
|
|
var ptr = NativeMethods.wickra_inertia_new((nuint)rviPeriod, (nuint)linregPeriod);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Inertia parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_inertia_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_inertia_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_inertia_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_inertia_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_inertia_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_inertia_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_inertia_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class InformationRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public InformationRatio(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_information_ratio_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid InformationRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_information_ratio_free);
|
|
}
|
|
|
|
public double Update(double x, double y)
|
|
{
|
|
var result = NativeMethods.wickra_information_ratio_update(_handle.DangerousGetHandle(), x, y);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> x, ReadOnlySpan<double> y)
|
|
{
|
|
var n = x.Length;
|
|
if (y.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* xPtr = x)
|
|
fixed (double* yPtr = y)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_information_ratio_batch(_handle.DangerousGetHandle(), xPtr, yPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_information_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_information_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_information_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_information_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class InitialBalance : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public InitialBalance(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_initial_balance_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid InitialBalance parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_initial_balance_free);
|
|
}
|
|
|
|
public InitialBalanceOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraInitialBalanceOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_initial_balance_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new InitialBalanceOutput(native.high, native.low) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_initial_balance_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_initial_balance_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_initial_balance_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_initial_balance_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class InstantaneousTrendline : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public InstantaneousTrendline(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_instantaneous_trendline_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid InstantaneousTrendline parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_instantaneous_trendline_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_instantaneous_trendline_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_instantaneous_trendline_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_instantaneous_trendline_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_instantaneous_trendline_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_instantaneous_trendline_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_instantaneous_trendline_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class IntradayIntensity : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public IntradayIntensity()
|
|
{
|
|
var ptr = NativeMethods.wickra_intraday_intensity_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid IntradayIntensity parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_intraday_intensity_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_intraday_intensity_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_intraday_intensity_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_intraday_intensity_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_intraday_intensity_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_intraday_intensity_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_intraday_intensity_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class IntradayMomentumIndex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public IntradayMomentumIndex(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_intraday_momentum_index_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid IntradayMomentumIndex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_intraday_momentum_index_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_intraday_momentum_index_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_intraday_momentum_index_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_intraday_momentum_index_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_intraday_momentum_index_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_intraday_momentum_index_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_intraday_momentum_index_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class IntradayVolatilityProfile : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
private readonly int _valuesCapacity;
|
|
|
|
public IntradayVolatilityProfile(int buckets, int utcOffsetMinutes)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(buckets);
|
|
var ptr = NativeMethods.wickra_intraday_volatility_profile_new((nuint)buckets, utcOffsetMinutes);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid IntradayVolatilityProfile parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_intraday_volatility_profile_free);
|
|
_valuesCapacity = buckets;
|
|
}
|
|
|
|
public double[]? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var values = new double[_valuesCapacity];
|
|
long length;
|
|
unsafe
|
|
{
|
|
fixed (double* valuesPtr = values)
|
|
{
|
|
length = (long)NativeMethods.wickra_intraday_volatility_profile_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, valuesPtr, (nuint)_valuesCapacity);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
if (length < 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (length < values.Length)
|
|
{
|
|
Array.Resize(ref values, (int)length);
|
|
}
|
|
|
|
return values;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_intraday_volatility_profile_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_intraday_volatility_profile_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_intraday_volatility_profile_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_intraday_volatility_profile_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class InverseFisherTransform : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public InverseFisherTransform(double scale)
|
|
{
|
|
var ptr = NativeMethods.wickra_inverse_fisher_transform_new(scale);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid InverseFisherTransform parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_inverse_fisher_transform_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_inverse_fisher_transform_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_inverse_fisher_transform_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_inverse_fisher_transform_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_inverse_fisher_transform_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_inverse_fisher_transform_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_inverse_fisher_transform_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class InvertedHammer : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public InvertedHammer()
|
|
{
|
|
var ptr = NativeMethods.wickra_inverted_hammer_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid InvertedHammer parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_inverted_hammer_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_inverted_hammer_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_inverted_hammer_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_inverted_hammer_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_inverted_hammer_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_inverted_hammer_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_inverted_hammer_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class JarqueBera : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public JarqueBera(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_jarque_bera_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid JarqueBera parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_jarque_bera_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_jarque_bera_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_jarque_bera_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_jarque_bera_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_jarque_bera_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_jarque_bera_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_jarque_bera_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Jma : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Jma(int period, double phase, uint power)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_jma_new((nuint)period, phase, power);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Jma parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_jma_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_jma_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_jma_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_jma_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_jma_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_jma_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_jma_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class JumpIndicator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public JumpIndicator(int period, double threshold)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_jump_indicator_new((nuint)period, threshold);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid JumpIndicator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_jump_indicator_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_jump_indicator_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_jump_indicator_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_jump_indicator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_jump_indicator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_jump_indicator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_jump_indicator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class KRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public KRatio(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_k_ratio_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid KRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_k_ratio_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_k_ratio_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_k_ratio_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_k_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_k_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_k_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_k_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class KagiBars : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public KagiBars(double reversal)
|
|
{
|
|
var ptr = NativeMethods.wickra_kagi_bars_new(reversal);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid KagiBars parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_kagi_bars_free);
|
|
}
|
|
|
|
public KagiBar[] Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
const int cap = 64;
|
|
Span<WickraKagiBar> buffer = stackalloc WickraKagiBar[cap];
|
|
long count;
|
|
unsafe
|
|
{
|
|
fixed (WickraKagiBar* ptr = buffer)
|
|
{
|
|
count = (long)NativeMethods.wickra_kagi_bars_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, ptr, (nuint)cap);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
if (count <= 0)
|
|
{
|
|
return Array.Empty<KagiBar>();
|
|
}
|
|
|
|
var result = new KagiBar[count];
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
result[i] = new KagiBar(buffer[i].start, buffer[i].end, buffer[i].direction);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_kagi_bars_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_kagi_bars_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class KalmanHedgeRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public KalmanHedgeRatio(double delta, double observationVar)
|
|
{
|
|
var ptr = NativeMethods.wickra_kalman_hedge_ratio_new(delta, observationVar);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid KalmanHedgeRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_kalman_hedge_ratio_free);
|
|
}
|
|
|
|
public KalmanHedgeRatioOutput? Update(double x, double y)
|
|
{
|
|
WickraKalmanHedgeRatioOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_kalman_hedge_ratio_update(_handle.DangerousGetHandle(), x, y, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new KalmanHedgeRatioOutput(native.hedge_ratio, native.intercept, native.spread) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_kalman_hedge_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_kalman_hedge_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_kalman_hedge_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_kalman_hedge_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Kama : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Kama(int erPeriod, int fast, int slow)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(erPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(fast);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(slow);
|
|
var ptr = NativeMethods.wickra_kama_new((nuint)erPeriod, (nuint)fast, (nuint)slow);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Kama parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_kama_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_kama_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_kama_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_kama_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_kama_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_kama_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_kama_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class KaseDevStop : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public KaseDevStop(int period, double dev)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_kase_dev_stop_new((nuint)period, dev);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid KaseDevStop parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_kase_dev_stop_free);
|
|
}
|
|
|
|
public KaseDevStopOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraKaseDevStopOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_kase_dev_stop_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new KaseDevStopOutput(native.@value, native.direction) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_kase_dev_stop_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_kase_dev_stop_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_kase_dev_stop_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_kase_dev_stop_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class KasePermissionStochastic : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public KasePermissionStochastic(int length, int smooth)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(length);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(smooth);
|
|
var ptr = NativeMethods.wickra_kase_permission_stochastic_new((nuint)length, (nuint)smooth);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid KasePermissionStochastic parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_kase_permission_stochastic_free);
|
|
}
|
|
|
|
public KasePermissionStochasticOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraKasePermissionStochasticOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_kase_permission_stochastic_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new KasePermissionStochasticOutput(native.fast, native.slow) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_kase_permission_stochastic_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_kase_permission_stochastic_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_kase_permission_stochastic_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_kase_permission_stochastic_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class KellyCriterion : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public KellyCriterion(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_kelly_criterion_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid KellyCriterion parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_kelly_criterion_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_kelly_criterion_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_kelly_criterion_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_kelly_criterion_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_kelly_criterion_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_kelly_criterion_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_kelly_criterion_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Keltner : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Keltner(int emaPeriod, int atrPeriod, double multiplier)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(emaPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(atrPeriod);
|
|
var ptr = NativeMethods.wickra_keltner_new((nuint)emaPeriod, (nuint)atrPeriod, multiplier);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Keltner parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_keltner_free);
|
|
}
|
|
|
|
public KeltnerOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraKeltnerOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_keltner_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new KeltnerOutput(native.upper, native.middle, native.lower) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_keltner_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_keltner_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_keltner_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_keltner_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class KendallTau : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public KendallTau(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_kendall_tau_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid KendallTau parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_kendall_tau_free);
|
|
}
|
|
|
|
public double Update(double x, double y)
|
|
{
|
|
var result = NativeMethods.wickra_kendall_tau_update(_handle.DangerousGetHandle(), x, y);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> x, ReadOnlySpan<double> y)
|
|
{
|
|
var n = x.Length;
|
|
if (y.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* xPtr = x)
|
|
fixed (double* yPtr = y)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_kendall_tau_batch(_handle.DangerousGetHandle(), xPtr, yPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_kendall_tau_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_kendall_tau_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_kendall_tau_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_kendall_tau_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Kicking : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Kicking()
|
|
{
|
|
var ptr = NativeMethods.wickra_kicking_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Kicking parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_kicking_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_kicking_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_kicking_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_kicking_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_kicking_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_kicking_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_kicking_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class KickingByLength : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public KickingByLength()
|
|
{
|
|
var ptr = NativeMethods.wickra_kicking_by_length_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid KickingByLength parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_kicking_by_length_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_kicking_by_length_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_kicking_by_length_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_kicking_by_length_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_kicking_by_length_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_kicking_by_length_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_kicking_by_length_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Kst : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Kst(int roc1, int roc2, int roc3, int roc4, int sma1, int sma2, int sma3, int sma4, int signal)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(roc1);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(roc2);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(roc3);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(roc4);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(sma1);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(sma2);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(sma3);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(sma4);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(signal);
|
|
var ptr = NativeMethods.wickra_kst_new((nuint)roc1, (nuint)roc2, (nuint)roc3, (nuint)roc4, (nuint)sma1, (nuint)sma2, (nuint)sma3, (nuint)sma4, (nuint)signal);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Kst parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_kst_free);
|
|
}
|
|
|
|
public KstOutput? Update(double @value)
|
|
{
|
|
WickraKstOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_kst_update(_handle.DangerousGetHandle(), @value, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new KstOutput(native.kst, native.signal) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_kst_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_kst_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_kst_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_kst_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Kurtosis : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Kurtosis(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_kurtosis_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Kurtosis parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_kurtosis_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_kurtosis_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_kurtosis_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_kurtosis_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_kurtosis_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_kurtosis_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_kurtosis_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Kvo : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Kvo(int fast, int slow)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(fast);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(slow);
|
|
var ptr = NativeMethods.wickra_kvo_new((nuint)fast, (nuint)slow);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Kvo parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_kvo_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_kvo_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_kvo_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_kvo_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_kvo_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_kvo_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_kvo_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class KylesLambda : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public KylesLambda(int window)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(window);
|
|
var ptr = NativeMethods.wickra_kyles_lambda_new((nuint)window);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid KylesLambda parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_kyles_lambda_free);
|
|
}
|
|
|
|
public double Update(double price, double size, bool isBuy, long timestamp, double mid)
|
|
{
|
|
var result = NativeMethods.wickra_kyles_lambda_update(_handle.DangerousGetHandle(), price, size, isBuy, timestamp, mid);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_kyles_lambda_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_kyles_lambda_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_kyles_lambda_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_kyles_lambda_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class LadderBottom : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public LadderBottom()
|
|
{
|
|
var ptr = NativeMethods.wickra_ladder_bottom_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid LadderBottom parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ladder_bottom_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_ladder_bottom_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_ladder_bottom_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ladder_bottom_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ladder_bottom_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ladder_bottom_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ladder_bottom_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class LaguerreRsi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public LaguerreRsi(double gamma)
|
|
{
|
|
var ptr = NativeMethods.wickra_laguerre_rsi_new(gamma);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid LaguerreRsi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_laguerre_rsi_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_laguerre_rsi_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_laguerre_rsi_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_laguerre_rsi_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_laguerre_rsi_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_laguerre_rsi_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_laguerre_rsi_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class LeadLagCrossCorrelation : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public LeadLagCrossCorrelation(int window, int maxLag)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(window);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(maxLag);
|
|
var ptr = NativeMethods.wickra_lead_lag_cross_correlation_new((nuint)window, (nuint)maxLag);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid LeadLagCrossCorrelation parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_lead_lag_cross_correlation_free);
|
|
}
|
|
|
|
public LeadLagCrossCorrelationOutput? Update(double x, double y)
|
|
{
|
|
WickraLeadLagCrossCorrelationOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_lead_lag_cross_correlation_update(_handle.DangerousGetHandle(), x, y, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new LeadLagCrossCorrelationOutput(native.lag, native.correlation) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_lead_lag_cross_correlation_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_lead_lag_cross_correlation_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_lead_lag_cross_correlation_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_lead_lag_cross_correlation_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class LinRegAngle : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public LinRegAngle(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_lin_reg_angle_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid LinRegAngle parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_lin_reg_angle_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_lin_reg_angle_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_lin_reg_angle_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_lin_reg_angle_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_lin_reg_angle_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_lin_reg_angle_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_lin_reg_angle_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class LinRegChannel : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public LinRegChannel(int period, double multiplier)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_lin_reg_channel_new((nuint)period, multiplier);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid LinRegChannel parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_lin_reg_channel_free);
|
|
}
|
|
|
|
public LinRegChannelOutput? Update(double @value)
|
|
{
|
|
WickraLinRegChannelOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_lin_reg_channel_update(_handle.DangerousGetHandle(), @value, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new LinRegChannelOutput(native.upper, native.middle, native.lower) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_lin_reg_channel_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_lin_reg_channel_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_lin_reg_channel_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_lin_reg_channel_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class LinRegIntercept : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public LinRegIntercept(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_lin_reg_intercept_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid LinRegIntercept parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_lin_reg_intercept_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_lin_reg_intercept_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_lin_reg_intercept_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_lin_reg_intercept_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_lin_reg_intercept_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_lin_reg_intercept_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_lin_reg_intercept_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class LinRegSlope : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public LinRegSlope(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_lin_reg_slope_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid LinRegSlope parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_lin_reg_slope_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_lin_reg_slope_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_lin_reg_slope_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_lin_reg_slope_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_lin_reg_slope_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_lin_reg_slope_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_lin_reg_slope_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class LinearRegression : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public LinearRegression(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_linear_regression_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid LinearRegression parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_linear_regression_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_linear_regression_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_linear_regression_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_linear_regression_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_linear_regression_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_linear_regression_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_linear_regression_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class LiquidationFeatures : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public LiquidationFeatures()
|
|
{
|
|
var ptr = NativeMethods.wickra_liquidation_features_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid LiquidationFeatures parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_liquidation_features_free);
|
|
}
|
|
|
|
public LiquidationFeaturesOutput? Update(double fundingRate, double markPrice, double indexPrice, double futuresPrice, double openInterest, double longSize, double shortSize, double takerBuyVolume, double takerSellVolume, double longLiquidation, double shortLiquidation, long timestamp)
|
|
{
|
|
WickraLiquidationFeaturesOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_liquidation_features_update(_handle.DangerousGetHandle(), fundingRate, markPrice, indexPrice, futuresPrice, openInterest, longSize, shortSize, takerBuyVolume, takerSellVolume, longLiquidation, shortLiquidation, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new LiquidationFeaturesOutput(native.long_, native.short_, native.net, native.total, native.imbalance) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_liquidation_features_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_liquidation_features_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_liquidation_features_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_liquidation_features_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class LogReturn : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public LogReturn(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_log_return_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid LogReturn parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_log_return_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_log_return_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_log_return_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_log_return_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_log_return_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_log_return_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_log_return_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class LongLeggedDoji : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public LongLeggedDoji()
|
|
{
|
|
var ptr = NativeMethods.wickra_long_legged_doji_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid LongLeggedDoji parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_long_legged_doji_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_long_legged_doji_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_long_legged_doji_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_long_legged_doji_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_long_legged_doji_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_long_legged_doji_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_long_legged_doji_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class LongLine : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public LongLine()
|
|
{
|
|
var ptr = NativeMethods.wickra_long_line_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid LongLine parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_long_line_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_long_line_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_long_line_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_long_line_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_long_line_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_long_line_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_long_line_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class LongShortRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public LongShortRatio()
|
|
{
|
|
var ptr = NativeMethods.wickra_long_short_ratio_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid LongShortRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_long_short_ratio_free);
|
|
}
|
|
|
|
public double Update(double fundingRate, double markPrice, double indexPrice, double futuresPrice, double openInterest, double longSize, double shortSize, double takerBuyVolume, double takerSellVolume, double longLiquidation, double shortLiquidation, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_long_short_ratio_update(_handle.DangerousGetHandle(), fundingRate, markPrice, indexPrice, futuresPrice, openInterest, longSize, shortSize, takerBuyVolume, takerSellVolume, longLiquidation, shortLiquidation, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_long_short_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_long_short_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_long_short_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_long_short_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class M2Measure : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public M2Measure(int period, double riskFree, double benchmarkStddev)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_m2_measure_new((nuint)period, riskFree, benchmarkStddev);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid M2Measure parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_m2_measure_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_m2_measure_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_m2_measure_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_m2_measure_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_m2_measure_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_m2_measure_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_m2_measure_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MaEnvelope : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MaEnvelope(int period, double percent)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_ma_envelope_new((nuint)period, percent);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MaEnvelope parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ma_envelope_free);
|
|
}
|
|
|
|
public MaEnvelopeOutput? Update(double @value)
|
|
{
|
|
WickraMaEnvelopeOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_ma_envelope_update(_handle.DangerousGetHandle(), @value, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new MaEnvelopeOutput(native.upper, native.middle, native.lower) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ma_envelope_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ma_envelope_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ma_envelope_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ma_envelope_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MacdExt : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MacdExt(int fast, byte fastType, int slow, byte slowType, int signal, byte signalType)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(fast);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(slow);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(signal);
|
|
var ptr = NativeMethods.wickra_macd_ext_new((nuint)fast, fastType, (nuint)slow, slowType, (nuint)signal, signalType);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MacdExt parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_macd_ext_free);
|
|
}
|
|
|
|
public MacdOutput? Update(double @value)
|
|
{
|
|
WickraMacdOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_macd_ext_update(_handle.DangerousGetHandle(), @value, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new MacdOutput(native.macd, native.signal, native.histogram) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_macd_ext_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_macd_ext_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_macd_ext_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_macd_ext_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MacdFix : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MacdFix(int signal)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(signal);
|
|
var ptr = NativeMethods.wickra_macd_fix_new((nuint)signal);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MacdFix parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_macd_fix_free);
|
|
}
|
|
|
|
public MacdOutput? Update(double @value)
|
|
{
|
|
WickraMacdOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_macd_fix_update(_handle.DangerousGetHandle(), @value, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new MacdOutput(native.macd, native.signal, native.histogram) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_macd_fix_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_macd_fix_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_macd_fix_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_macd_fix_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MacdHistogram : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MacdHistogram(int fast, int slow, int signal)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(fast);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(slow);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(signal);
|
|
var ptr = NativeMethods.wickra_macd_histogram_new((nuint)fast, (nuint)slow, (nuint)signal);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MacdHistogram parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_macd_histogram_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_macd_histogram_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_macd_histogram_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_macd_histogram_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_macd_histogram_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_macd_histogram_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_macd_histogram_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MacdIndicator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MacdIndicator(int fast, int slow, int signal)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(fast);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(slow);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(signal);
|
|
var ptr = NativeMethods.wickra_macd_indicator_new((nuint)fast, (nuint)slow, (nuint)signal);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MacdIndicator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_macd_indicator_free);
|
|
}
|
|
|
|
public MacdOutput? Update(double @value)
|
|
{
|
|
WickraMacdOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_macd_indicator_update(_handle.DangerousGetHandle(), @value, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new MacdOutput(native.macd, native.signal, native.histogram) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_macd_indicator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_macd_indicator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_macd_indicator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_macd_indicator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Mama : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Mama(double fastLimit, double slowLimit)
|
|
{
|
|
var ptr = NativeMethods.wickra_mama_new(fastLimit, slowLimit);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Mama parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_mama_free);
|
|
}
|
|
|
|
public MamaOutput? Update(double @value)
|
|
{
|
|
WickraMamaOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_mama_update(_handle.DangerousGetHandle(), @value, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new MamaOutput(native.mama, native.fama) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_mama_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_mama_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_mama_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_mama_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MarketFacilitationIndex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MarketFacilitationIndex()
|
|
{
|
|
var ptr = NativeMethods.wickra_market_facilitation_index_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MarketFacilitationIndex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_market_facilitation_index_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_market_facilitation_index_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_market_facilitation_index_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_market_facilitation_index_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_market_facilitation_index_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_market_facilitation_index_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_market_facilitation_index_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MartinRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MartinRatio(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_martin_ratio_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MartinRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_martin_ratio_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_martin_ratio_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_martin_ratio_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_martin_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_martin_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_martin_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_martin_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Marubozu : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Marubozu()
|
|
{
|
|
var ptr = NativeMethods.wickra_marubozu_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Marubozu parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_marubozu_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_marubozu_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_marubozu_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_marubozu_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_marubozu_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_marubozu_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_marubozu_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MassIndex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MassIndex(int emaPeriod, int sumPeriod)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(emaPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(sumPeriod);
|
|
var ptr = NativeMethods.wickra_mass_index_new((nuint)emaPeriod, (nuint)sumPeriod);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MassIndex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_mass_index_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_mass_index_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_mass_index_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_mass_index_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_mass_index_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_mass_index_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_mass_index_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MatHold : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MatHold()
|
|
{
|
|
var ptr = NativeMethods.wickra_mat_hold_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MatHold parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_mat_hold_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_mat_hold_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_mat_hold_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_mat_hold_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_mat_hold_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_mat_hold_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_mat_hold_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MatchingLow : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MatchingLow()
|
|
{
|
|
var ptr = NativeMethods.wickra_matching_low_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MatchingLow parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_matching_low_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_matching_low_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_matching_low_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_matching_low_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_matching_low_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_matching_low_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_matching_low_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MaxDrawdown : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MaxDrawdown(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_max_drawdown_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MaxDrawdown parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_max_drawdown_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_max_drawdown_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_max_drawdown_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_max_drawdown_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_max_drawdown_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_max_drawdown_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_max_drawdown_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class McClellanOscillator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public McClellanOscillator()
|
|
{
|
|
var ptr = NativeMethods.wickra_mc_clellan_oscillator_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid McClellanOscillator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_mc_clellan_oscillator_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> change, ReadOnlySpan<double> volume, ReadOnlySpan<bool> newHigh, ReadOnlySpan<bool> newLow, ReadOnlySpan<bool> aboveMa, ReadOnlySpan<bool> onBuySignal, long timestamp)
|
|
{
|
|
if (volume.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newHigh.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newLow.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (aboveMa.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (onBuySignal.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* changePtr = change)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (bool* newHighPtr = newHigh)
|
|
fixed (bool* newLowPtr = newLow)
|
|
fixed (bool* aboveMaPtr = aboveMa)
|
|
fixed (bool* onBuySignalPtr = onBuySignal)
|
|
{
|
|
result = NativeMethods.wickra_mc_clellan_oscillator_update(_handle.DangerousGetHandle(), changePtr, volumePtr, newHighPtr, newLowPtr, aboveMaPtr, onBuySignalPtr, (nuint)change.Length, timestamp);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_mc_clellan_oscillator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_mc_clellan_oscillator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_mc_clellan_oscillator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_mc_clellan_oscillator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class McClellanSummationIndex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public McClellanSummationIndex()
|
|
{
|
|
var ptr = NativeMethods.wickra_mc_clellan_summation_index_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid McClellanSummationIndex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_mc_clellan_summation_index_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> change, ReadOnlySpan<double> volume, ReadOnlySpan<bool> newHigh, ReadOnlySpan<bool> newLow, ReadOnlySpan<bool> aboveMa, ReadOnlySpan<bool> onBuySignal, long timestamp)
|
|
{
|
|
if (volume.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newHigh.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newLow.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (aboveMa.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (onBuySignal.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* changePtr = change)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (bool* newHighPtr = newHigh)
|
|
fixed (bool* newLowPtr = newLow)
|
|
fixed (bool* aboveMaPtr = aboveMa)
|
|
fixed (bool* onBuySignalPtr = onBuySignal)
|
|
{
|
|
result = NativeMethods.wickra_mc_clellan_summation_index_update(_handle.DangerousGetHandle(), changePtr, volumePtr, newHighPtr, newLowPtr, aboveMaPtr, onBuySignalPtr, (nuint)change.Length, timestamp);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_mc_clellan_summation_index_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_mc_clellan_summation_index_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_mc_clellan_summation_index_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_mc_clellan_summation_index_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class McGinleyDynamic : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public McGinleyDynamic(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_mc_ginley_dynamic_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid McGinleyDynamic parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_mc_ginley_dynamic_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_mc_ginley_dynamic_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_mc_ginley_dynamic_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_mc_ginley_dynamic_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_mc_ginley_dynamic_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_mc_ginley_dynamic_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_mc_ginley_dynamic_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MedianAbsoluteDeviation : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MedianAbsoluteDeviation(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_median_absolute_deviation_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MedianAbsoluteDeviation parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_median_absolute_deviation_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_median_absolute_deviation_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_median_absolute_deviation_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_median_absolute_deviation_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_median_absolute_deviation_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_median_absolute_deviation_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_median_absolute_deviation_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MedianChannel : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MedianChannel(int period, double multiplier)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_median_channel_new((nuint)period, multiplier);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MedianChannel parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_median_channel_free);
|
|
}
|
|
|
|
public MedianChannelOutput? Update(double @value)
|
|
{
|
|
WickraMedianChannelOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_median_channel_update(_handle.DangerousGetHandle(), @value, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new MedianChannelOutput(native.upper, native.middle, native.lower) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_median_channel_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_median_channel_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_median_channel_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_median_channel_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MedianMa : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MedianMa(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_median_ma_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MedianMa parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_median_ma_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_median_ma_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_median_ma_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_median_ma_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_median_ma_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_median_ma_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_median_ma_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MedianPrice : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MedianPrice()
|
|
{
|
|
var ptr = NativeMethods.wickra_median_price_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MedianPrice parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_median_price_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_median_price_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_median_price_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_median_price_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_median_price_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_median_price_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_median_price_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Mfi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Mfi(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_mfi_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Mfi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_mfi_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_mfi_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_mfi_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_mfi_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_mfi_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_mfi_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_mfi_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Microprice : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Microprice()
|
|
{
|
|
var ptr = NativeMethods.wickra_microprice_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Microprice parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_microprice_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> bidPrice, ReadOnlySpan<double> bidSize, ReadOnlySpan<double> askPrice, ReadOnlySpan<double> askSize)
|
|
{
|
|
if (bidSize.Length != bidPrice.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (askSize.Length != askPrice.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* bidPricePtr = bidPrice)
|
|
fixed (double* bidSizePtr = bidSize)
|
|
fixed (double* askPricePtr = askPrice)
|
|
fixed (double* askSizePtr = askSize)
|
|
{
|
|
result = NativeMethods.wickra_microprice_update(_handle.DangerousGetHandle(), bidPricePtr, bidSizePtr, (nuint)bidPrice.Length, askPricePtr, askSizePtr, (nuint)askPrice.Length);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_microprice_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_microprice_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_microprice_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_microprice_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MidPoint : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MidPoint(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_mid_point_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MidPoint parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_mid_point_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_mid_point_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_mid_point_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_mid_point_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_mid_point_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_mid_point_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_mid_point_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MidPrice : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MidPrice(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_mid_price_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MidPrice parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_mid_price_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_mid_price_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_mid_price_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_mid_price_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_mid_price_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_mid_price_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_mid_price_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MinusDi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MinusDi(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_minus_di_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MinusDi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_minus_di_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_minus_di_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_minus_di_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_minus_di_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_minus_di_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_minus_di_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_minus_di_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MinusDm : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MinusDm(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_minus_dm_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MinusDm parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_minus_dm_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_minus_dm_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_minus_dm_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_minus_dm_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_minus_dm_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_minus_dm_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_minus_dm_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ModifiedMaStop : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ModifiedMaStop(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_modified_ma_stop_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ModifiedMaStop parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_modified_ma_stop_free);
|
|
}
|
|
|
|
public ModifiedMaStopOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraModifiedMaStopOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_modified_ma_stop_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new ModifiedMaStopOutput(native.@value, native.direction) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_modified_ma_stop_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_modified_ma_stop_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_modified_ma_stop_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_modified_ma_stop_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Mom : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Mom(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_mom_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Mom parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_mom_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_mom_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_mom_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_mom_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_mom_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_mom_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_mom_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MorningDojiStar : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MorningDojiStar()
|
|
{
|
|
var ptr = NativeMethods.wickra_morning_doji_star_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MorningDojiStar parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_morning_doji_star_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_morning_doji_star_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_morning_doji_star_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_morning_doji_star_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_morning_doji_star_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_morning_doji_star_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_morning_doji_star_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MorningEveningStar : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MorningEveningStar()
|
|
{
|
|
var ptr = NativeMethods.wickra_morning_evening_star_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MorningEveningStar parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_morning_evening_star_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_morning_evening_star_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_morning_evening_star_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_morning_evening_star_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_morning_evening_star_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_morning_evening_star_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_morning_evening_star_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class MurreyMathLines : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public MurreyMathLines(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_murrey_math_lines_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid MurreyMathLines parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_murrey_math_lines_free);
|
|
}
|
|
|
|
public MurreyMathLinesOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraMurreyMathLinesOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_murrey_math_lines_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new MurreyMathLinesOutput(native.mm8_8, native.mm7_8, native.mm6_8, native.mm5_8, native.mm4_8, native.mm3_8, native.mm2_8, native.mm1_8, native.mm0_8) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_murrey_math_lines_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_murrey_math_lines_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_murrey_math_lines_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_murrey_math_lines_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class NakedPoc : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public NakedPoc(int sessionLen, int bins)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(sessionLen);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(bins);
|
|
var ptr = NativeMethods.wickra_naked_poc_new((nuint)sessionLen, (nuint)bins);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid NakedPoc parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_naked_poc_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_naked_poc_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_naked_poc_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_naked_poc_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_naked_poc_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_naked_poc_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_naked_poc_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Natr : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Natr(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_natr_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Natr parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_natr_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_natr_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_natr_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_natr_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_natr_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_natr_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_natr_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class NewHighsNewLows : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public NewHighsNewLows()
|
|
{
|
|
var ptr = NativeMethods.wickra_new_highs_new_lows_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid NewHighsNewLows parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_new_highs_new_lows_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> change, ReadOnlySpan<double> volume, ReadOnlySpan<bool> newHigh, ReadOnlySpan<bool> newLow, ReadOnlySpan<bool> aboveMa, ReadOnlySpan<bool> onBuySignal, long timestamp)
|
|
{
|
|
if (volume.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newHigh.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newLow.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (aboveMa.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (onBuySignal.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* changePtr = change)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (bool* newHighPtr = newHigh)
|
|
fixed (bool* newLowPtr = newLow)
|
|
fixed (bool* aboveMaPtr = aboveMa)
|
|
fixed (bool* onBuySignalPtr = onBuySignal)
|
|
{
|
|
result = NativeMethods.wickra_new_highs_new_lows_update(_handle.DangerousGetHandle(), changePtr, volumePtr, newHighPtr, newLowPtr, aboveMaPtr, onBuySignalPtr, (nuint)change.Length, timestamp);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_new_highs_new_lows_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_new_highs_new_lows_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_new_highs_new_lows_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_new_highs_new_lows_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class NewPriceLines : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public NewPriceLines(int count)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(count);
|
|
var ptr = NativeMethods.wickra_new_price_lines_new((nuint)count);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid NewPriceLines parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_new_price_lines_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_new_price_lines_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_new_price_lines_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_new_price_lines_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_new_price_lines_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_new_price_lines_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_new_price_lines_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Nrtr : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Nrtr(double pct)
|
|
{
|
|
var ptr = NativeMethods.wickra_nrtr_new(pct);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Nrtr parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_nrtr_free);
|
|
}
|
|
|
|
public NrtrOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraNrtrOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_nrtr_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new NrtrOutput(native.@value, native.direction) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_nrtr_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_nrtr_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_nrtr_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_nrtr_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Nvi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Nvi()
|
|
{
|
|
var ptr = NativeMethods.wickra_nvi_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Nvi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_nvi_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_nvi_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_nvi_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_nvi_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_nvi_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_nvi_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_nvi_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Obv : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Obv()
|
|
{
|
|
var ptr = NativeMethods.wickra_obv_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Obv parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_obv_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_obv_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_obv_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_obv_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_obv_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_obv_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_obv_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class OIPriceDivergence : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public OIPriceDivergence(int window)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(window);
|
|
var ptr = NativeMethods.wickra_oi_price_divergence_new((nuint)window);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid OIPriceDivergence parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_oi_price_divergence_free);
|
|
}
|
|
|
|
public double Update(double fundingRate, double markPrice, double indexPrice, double futuresPrice, double openInterest, double longSize, double shortSize, double takerBuyVolume, double takerSellVolume, double longLiquidation, double shortLiquidation, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_oi_price_divergence_update(_handle.DangerousGetHandle(), fundingRate, markPrice, indexPrice, futuresPrice, openInterest, longSize, shortSize, takerBuyVolume, takerSellVolume, longLiquidation, shortLiquidation, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_oi_price_divergence_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_oi_price_divergence_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_oi_price_divergence_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_oi_price_divergence_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class OiToVolumeRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public OiToVolumeRatio()
|
|
{
|
|
var ptr = NativeMethods.wickra_oi_to_volume_ratio_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid OiToVolumeRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_oi_to_volume_ratio_free);
|
|
}
|
|
|
|
public double Update(double fundingRate, double markPrice, double indexPrice, double futuresPrice, double openInterest, double longSize, double shortSize, double takerBuyVolume, double takerSellVolume, double longLiquidation, double shortLiquidation, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_oi_to_volume_ratio_update(_handle.DangerousGetHandle(), fundingRate, markPrice, indexPrice, futuresPrice, openInterest, longSize, shortSize, takerBuyVolume, takerSellVolume, longLiquidation, shortLiquidation, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_oi_to_volume_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_oi_to_volume_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_oi_to_volume_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_oi_to_volume_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class OIWeighted : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public OIWeighted()
|
|
{
|
|
var ptr = NativeMethods.wickra_oi_weighted_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid OIWeighted parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_oi_weighted_free);
|
|
}
|
|
|
|
public double Update(double fundingRate, double markPrice, double indexPrice, double futuresPrice, double openInterest, double longSize, double shortSize, double takerBuyVolume, double takerSellVolume, double longLiquidation, double shortLiquidation, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_oi_weighted_update(_handle.DangerousGetHandle(), fundingRate, markPrice, indexPrice, futuresPrice, openInterest, longSize, shortSize, takerBuyVolume, takerSellVolume, longLiquidation, shortLiquidation, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_oi_weighted_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_oi_weighted_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_oi_weighted_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_oi_weighted_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class OmegaRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public OmegaRatio(int period, double threshold)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_omega_ratio_new((nuint)period, threshold);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid OmegaRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_omega_ratio_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_omega_ratio_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_omega_ratio_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_omega_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_omega_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_omega_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_omega_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class OnNeck : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public OnNeck()
|
|
{
|
|
var ptr = NativeMethods.wickra_on_neck_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid OnNeck parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_on_neck_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_on_neck_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_on_neck_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_on_neck_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_on_neck_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_on_neck_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_on_neck_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class OpenInterestDelta : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public OpenInterestDelta()
|
|
{
|
|
var ptr = NativeMethods.wickra_open_interest_delta_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid OpenInterestDelta parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_open_interest_delta_free);
|
|
}
|
|
|
|
public double Update(double fundingRate, double markPrice, double indexPrice, double futuresPrice, double openInterest, double longSize, double shortSize, double takerBuyVolume, double takerSellVolume, double longLiquidation, double shortLiquidation, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_open_interest_delta_update(_handle.DangerousGetHandle(), fundingRate, markPrice, indexPrice, futuresPrice, openInterest, longSize, shortSize, takerBuyVolume, takerSellVolume, longLiquidation, shortLiquidation, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_open_interest_delta_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_open_interest_delta_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_open_interest_delta_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_open_interest_delta_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class OpenInterestMomentum : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public OpenInterestMomentum(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_open_interest_momentum_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid OpenInterestMomentum parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_open_interest_momentum_free);
|
|
}
|
|
|
|
public double Update(double fundingRate, double markPrice, double indexPrice, double futuresPrice, double openInterest, double longSize, double shortSize, double takerBuyVolume, double takerSellVolume, double longLiquidation, double shortLiquidation, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_open_interest_momentum_update(_handle.DangerousGetHandle(), fundingRate, markPrice, indexPrice, futuresPrice, openInterest, longSize, shortSize, takerBuyVolume, takerSellVolume, longLiquidation, shortLiquidation, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_open_interest_momentum_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_open_interest_momentum_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_open_interest_momentum_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_open_interest_momentum_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class OpeningMarubozu : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public OpeningMarubozu()
|
|
{
|
|
var ptr = NativeMethods.wickra_opening_marubozu_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid OpeningMarubozu parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_opening_marubozu_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_opening_marubozu_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_opening_marubozu_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_opening_marubozu_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_opening_marubozu_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_opening_marubozu_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_opening_marubozu_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class OpeningRange : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public OpeningRange(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_opening_range_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid OpeningRange parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_opening_range_free);
|
|
}
|
|
|
|
public OpeningRangeOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraOpeningRangeOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_opening_range_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new OpeningRangeOutput(native.high, native.low, native.breakout_distance) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_opening_range_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_opening_range_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_opening_range_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_opening_range_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class OrderBookImbalanceFull : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public OrderBookImbalanceFull()
|
|
{
|
|
var ptr = NativeMethods.wickra_order_book_imbalance_full_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid OrderBookImbalanceFull parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_order_book_imbalance_full_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> bidPrice, ReadOnlySpan<double> bidSize, ReadOnlySpan<double> askPrice, ReadOnlySpan<double> askSize)
|
|
{
|
|
if (bidSize.Length != bidPrice.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (askSize.Length != askPrice.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* bidPricePtr = bidPrice)
|
|
fixed (double* bidSizePtr = bidSize)
|
|
fixed (double* askPricePtr = askPrice)
|
|
fixed (double* askSizePtr = askSize)
|
|
{
|
|
result = NativeMethods.wickra_order_book_imbalance_full_update(_handle.DangerousGetHandle(), bidPricePtr, bidSizePtr, (nuint)bidPrice.Length, askPricePtr, askSizePtr, (nuint)askPrice.Length);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_order_book_imbalance_full_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_order_book_imbalance_full_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_order_book_imbalance_full_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_order_book_imbalance_full_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class OrderBookImbalanceTop1 : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public OrderBookImbalanceTop1()
|
|
{
|
|
var ptr = NativeMethods.wickra_order_book_imbalance_top1_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid OrderBookImbalanceTop1 parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_order_book_imbalance_top1_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> bidPrice, ReadOnlySpan<double> bidSize, ReadOnlySpan<double> askPrice, ReadOnlySpan<double> askSize)
|
|
{
|
|
if (bidSize.Length != bidPrice.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (askSize.Length != askPrice.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* bidPricePtr = bidPrice)
|
|
fixed (double* bidSizePtr = bidSize)
|
|
fixed (double* askPricePtr = askPrice)
|
|
fixed (double* askSizePtr = askSize)
|
|
{
|
|
result = NativeMethods.wickra_order_book_imbalance_top1_update(_handle.DangerousGetHandle(), bidPricePtr, bidSizePtr, (nuint)bidPrice.Length, askPricePtr, askSizePtr, (nuint)askPrice.Length);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_order_book_imbalance_top1_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_order_book_imbalance_top1_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_order_book_imbalance_top1_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_order_book_imbalance_top1_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class OrderBookImbalanceTopN : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public OrderBookImbalanceTopN(int levels)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(levels);
|
|
var ptr = NativeMethods.wickra_order_book_imbalance_top_n_new((nuint)levels);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid OrderBookImbalanceTopN parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_order_book_imbalance_top_n_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> bidPrice, ReadOnlySpan<double> bidSize, ReadOnlySpan<double> askPrice, ReadOnlySpan<double> askSize)
|
|
{
|
|
if (bidSize.Length != bidPrice.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (askSize.Length != askPrice.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* bidPricePtr = bidPrice)
|
|
fixed (double* bidSizePtr = bidSize)
|
|
fixed (double* askPricePtr = askPrice)
|
|
fixed (double* askSizePtr = askSize)
|
|
{
|
|
result = NativeMethods.wickra_order_book_imbalance_top_n_update(_handle.DangerousGetHandle(), bidPricePtr, bidSizePtr, (nuint)bidPrice.Length, askPricePtr, askSizePtr, (nuint)askPrice.Length);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_order_book_imbalance_top_n_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_order_book_imbalance_top_n_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_order_book_imbalance_top_n_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_order_book_imbalance_top_n_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class OrderFlowImbalance : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public OrderFlowImbalance(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_order_flow_imbalance_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid OrderFlowImbalance parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_order_flow_imbalance_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> bidPrice, ReadOnlySpan<double> bidSize, ReadOnlySpan<double> askPrice, ReadOnlySpan<double> askSize)
|
|
{
|
|
if (bidSize.Length != bidPrice.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (askSize.Length != askPrice.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* bidPricePtr = bidPrice)
|
|
fixed (double* bidSizePtr = bidSize)
|
|
fixed (double* askPricePtr = askPrice)
|
|
fixed (double* askSizePtr = askSize)
|
|
{
|
|
result = NativeMethods.wickra_order_flow_imbalance_update(_handle.DangerousGetHandle(), bidPricePtr, bidSizePtr, (nuint)bidPrice.Length, askPricePtr, askSizePtr, (nuint)askPrice.Length);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_order_flow_imbalance_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_order_flow_imbalance_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_order_flow_imbalance_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_order_flow_imbalance_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class OuHalfLife : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public OuHalfLife(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_ou_half_life_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid OuHalfLife parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ou_half_life_free);
|
|
}
|
|
|
|
public double Update(double x, double y)
|
|
{
|
|
var result = NativeMethods.wickra_ou_half_life_update(_handle.DangerousGetHandle(), x, y);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> x, ReadOnlySpan<double> y)
|
|
{
|
|
var n = x.Length;
|
|
if (y.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* xPtr = x)
|
|
fixed (double* yPtr = y)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_ou_half_life_batch(_handle.DangerousGetHandle(), xPtr, yPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ou_half_life_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ou_half_life_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ou_half_life_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ou_half_life_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class OvernightGap : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public OvernightGap(int utcOffsetMinutes)
|
|
{
|
|
var ptr = NativeMethods.wickra_overnight_gap_new(utcOffsetMinutes);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid OvernightGap parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_overnight_gap_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_overnight_gap_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_overnight_gap_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_overnight_gap_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_overnight_gap_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_overnight_gap_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_overnight_gap_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class OvernightIntradayReturn : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public OvernightIntradayReturn(int utcOffsetMinutes)
|
|
{
|
|
var ptr = NativeMethods.wickra_overnight_intraday_return_new(utcOffsetMinutes);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid OvernightIntradayReturn parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_overnight_intraday_return_free);
|
|
}
|
|
|
|
public OvernightIntradayReturnOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraOvernightIntradayReturnOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_overnight_intraday_return_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new OvernightIntradayReturnOutput(native.overnight, native.intraday) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_overnight_intraday_return_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_overnight_intraday_return_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_overnight_intraday_return_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_overnight_intraday_return_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class PainIndex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public PainIndex(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_pain_index_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid PainIndex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_pain_index_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_pain_index_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_pain_index_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_pain_index_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_pain_index_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_pain_index_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_pain_index_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class PairSpreadZScore : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public PairSpreadZScore(int betaPeriod, int zPeriod)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(betaPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(zPeriod);
|
|
var ptr = NativeMethods.wickra_pair_spread_z_score_new((nuint)betaPeriod, (nuint)zPeriod);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid PairSpreadZScore parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_pair_spread_z_score_free);
|
|
}
|
|
|
|
public double Update(double x, double y)
|
|
{
|
|
var result = NativeMethods.wickra_pair_spread_z_score_update(_handle.DangerousGetHandle(), x, y);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> x, ReadOnlySpan<double> y)
|
|
{
|
|
var n = x.Length;
|
|
if (y.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* xPtr = x)
|
|
fixed (double* yPtr = y)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_pair_spread_z_score_batch(_handle.DangerousGetHandle(), xPtr, yPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_pair_spread_z_score_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_pair_spread_z_score_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_pair_spread_z_score_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_pair_spread_z_score_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class PairwiseBeta : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public PairwiseBeta(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_pairwise_beta_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid PairwiseBeta parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_pairwise_beta_free);
|
|
}
|
|
|
|
public double Update(double x, double y)
|
|
{
|
|
var result = NativeMethods.wickra_pairwise_beta_update(_handle.DangerousGetHandle(), x, y);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> x, ReadOnlySpan<double> y)
|
|
{
|
|
var n = x.Length;
|
|
if (y.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* xPtr = x)
|
|
fixed (double* yPtr = y)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_pairwise_beta_batch(_handle.DangerousGetHandle(), xPtr, yPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_pairwise_beta_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_pairwise_beta_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_pairwise_beta_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_pairwise_beta_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ParkinsonVolatility : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ParkinsonVolatility(int period, int tradingPeriods)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(tradingPeriods);
|
|
var ptr = NativeMethods.wickra_parkinson_volatility_new((nuint)period, (nuint)tradingPeriods);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ParkinsonVolatility parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_parkinson_volatility_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_parkinson_volatility_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_parkinson_volatility_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_parkinson_volatility_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_parkinson_volatility_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_parkinson_volatility_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_parkinson_volatility_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class PearsonCorrelation : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public PearsonCorrelation(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_pearson_correlation_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid PearsonCorrelation parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_pearson_correlation_free);
|
|
}
|
|
|
|
public double Update(double x, double y)
|
|
{
|
|
var result = NativeMethods.wickra_pearson_correlation_update(_handle.DangerousGetHandle(), x, y);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> x, ReadOnlySpan<double> y)
|
|
{
|
|
var n = x.Length;
|
|
if (y.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* xPtr = x)
|
|
fixed (double* yPtr = y)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_pearson_correlation_batch(_handle.DangerousGetHandle(), xPtr, yPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_pearson_correlation_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_pearson_correlation_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_pearson_correlation_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_pearson_correlation_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class PercentAboveMa : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public PercentAboveMa()
|
|
{
|
|
var ptr = NativeMethods.wickra_percent_above_ma_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid PercentAboveMa parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_percent_above_ma_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> change, ReadOnlySpan<double> volume, ReadOnlySpan<bool> newHigh, ReadOnlySpan<bool> newLow, ReadOnlySpan<bool> aboveMa, ReadOnlySpan<bool> onBuySignal, long timestamp)
|
|
{
|
|
if (volume.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newHigh.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newLow.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (aboveMa.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (onBuySignal.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* changePtr = change)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (bool* newHighPtr = newHigh)
|
|
fixed (bool* newLowPtr = newLow)
|
|
fixed (bool* aboveMaPtr = aboveMa)
|
|
fixed (bool* onBuySignalPtr = onBuySignal)
|
|
{
|
|
result = NativeMethods.wickra_percent_above_ma_update(_handle.DangerousGetHandle(), changePtr, volumePtr, newHighPtr, newLowPtr, aboveMaPtr, onBuySignalPtr, (nuint)change.Length, timestamp);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_percent_above_ma_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_percent_above_ma_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_percent_above_ma_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_percent_above_ma_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class PercentB : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public PercentB(int period, double multiplier)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_percent_b_new((nuint)period, multiplier);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid PercentB parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_percent_b_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_percent_b_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_percent_b_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_percent_b_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_percent_b_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_percent_b_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_percent_b_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class PercentageTrailingStop : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public PercentageTrailingStop(double percent)
|
|
{
|
|
var ptr = NativeMethods.wickra_percentage_trailing_stop_new(percent);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid PercentageTrailingStop parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_percentage_trailing_stop_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_percentage_trailing_stop_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_percentage_trailing_stop_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_percentage_trailing_stop_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_percentage_trailing_stop_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_percentage_trailing_stop_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_percentage_trailing_stop_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class PerpetualPremiumIndex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public PerpetualPremiumIndex()
|
|
{
|
|
var ptr = NativeMethods.wickra_perpetual_premium_index_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid PerpetualPremiumIndex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_perpetual_premium_index_free);
|
|
}
|
|
|
|
public double Update(double fundingRate, double markPrice, double indexPrice, double futuresPrice, double openInterest, double longSize, double shortSize, double takerBuyVolume, double takerSellVolume, double longLiquidation, double shortLiquidation, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_perpetual_premium_index_update(_handle.DangerousGetHandle(), fundingRate, markPrice, indexPrice, futuresPrice, openInterest, longSize, shortSize, takerBuyVolume, takerSellVolume, longLiquidation, shortLiquidation, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_perpetual_premium_index_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_perpetual_premium_index_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_perpetual_premium_index_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_perpetual_premium_index_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Pgo : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Pgo(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_pgo_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Pgo parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_pgo_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_pgo_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_pgo_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_pgo_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_pgo_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_pgo_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_pgo_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class PiercingDarkCloud : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public PiercingDarkCloud()
|
|
{
|
|
var ptr = NativeMethods.wickra_piercing_dark_cloud_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid PiercingDarkCloud parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_piercing_dark_cloud_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_piercing_dark_cloud_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_piercing_dark_cloud_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_piercing_dark_cloud_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_piercing_dark_cloud_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_piercing_dark_cloud_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_piercing_dark_cloud_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Pin : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Pin(int window)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(window);
|
|
var ptr = NativeMethods.wickra_pin_new((nuint)window);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Pin parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_pin_free);
|
|
}
|
|
|
|
public double Update(double price, double size, bool isBuy, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_pin_update(_handle.DangerousGetHandle(), price, size, isBuy, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_pin_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_pin_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_pin_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_pin_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class PivotReversal : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public PivotReversal(int left, int right)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(left);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(right);
|
|
var ptr = NativeMethods.wickra_pivot_reversal_new((nuint)left, (nuint)right);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid PivotReversal parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_pivot_reversal_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_pivot_reversal_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_pivot_reversal_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_pivot_reversal_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_pivot_reversal_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_pivot_reversal_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_pivot_reversal_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class PlusDi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public PlusDi(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_plus_di_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid PlusDi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_plus_di_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_plus_di_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_plus_di_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_plus_di_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_plus_di_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_plus_di_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_plus_di_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class PlusDm : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public PlusDm(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_plus_dm_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid PlusDm parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_plus_dm_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_plus_dm_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_plus_dm_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_plus_dm_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_plus_dm_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_plus_dm_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_plus_dm_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Pmo : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Pmo(int smoothing1, int smoothing2)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(smoothing1);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(smoothing2);
|
|
var ptr = NativeMethods.wickra_pmo_new((nuint)smoothing1, (nuint)smoothing2);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Pmo parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_pmo_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_pmo_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_pmo_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_pmo_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_pmo_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_pmo_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_pmo_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class PointAndFigureBars : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public PointAndFigureBars(double boxSize, int reversal)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(reversal);
|
|
var ptr = NativeMethods.wickra_point_and_figure_bars_new(boxSize, (nuint)reversal);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid PointAndFigureBars parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_point_and_figure_bars_free);
|
|
}
|
|
|
|
public PnfColumn[] Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
const int cap = 64;
|
|
Span<WickraPnfColumn> buffer = stackalloc WickraPnfColumn[cap];
|
|
long count;
|
|
unsafe
|
|
{
|
|
fixed (WickraPnfColumn* ptr = buffer)
|
|
{
|
|
count = (long)NativeMethods.wickra_point_and_figure_bars_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, ptr, (nuint)cap);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
if (count <= 0)
|
|
{
|
|
return Array.Empty<PnfColumn>();
|
|
}
|
|
|
|
var result = new PnfColumn[count];
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
result[i] = new PnfColumn(buffer[i].direction, buffer[i].high, buffer[i].low);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_point_and_figure_bars_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_point_and_figure_bars_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class PolarizedFractalEfficiency : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public PolarizedFractalEfficiency(int period, int smoothing)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(smoothing);
|
|
var ptr = NativeMethods.wickra_polarized_fractal_efficiency_new((nuint)period, (nuint)smoothing);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid PolarizedFractalEfficiency parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_polarized_fractal_efficiency_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_polarized_fractal_efficiency_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_polarized_fractal_efficiency_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_polarized_fractal_efficiency_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_polarized_fractal_efficiency_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_polarized_fractal_efficiency_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_polarized_fractal_efficiency_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Ppo : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Ppo(int fast, int slow)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(fast);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(slow);
|
|
var ptr = NativeMethods.wickra_ppo_new((nuint)fast, (nuint)slow);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Ppo parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ppo_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_ppo_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_ppo_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ppo_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ppo_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ppo_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ppo_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class PpoHistogram : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public PpoHistogram(int fast, int slow, int signal)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(fast);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(slow);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(signal);
|
|
var ptr = NativeMethods.wickra_ppo_histogram_new((nuint)fast, (nuint)slow, (nuint)signal);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid PpoHistogram parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ppo_histogram_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_ppo_histogram_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_ppo_histogram_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ppo_histogram_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ppo_histogram_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ppo_histogram_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ppo_histogram_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ProfileShape : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ProfileShape(int period, int bins)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(bins);
|
|
var ptr = NativeMethods.wickra_profile_shape_new((nuint)period, (nuint)bins);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ProfileShape parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_profile_shape_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_profile_shape_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_profile_shape_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_profile_shape_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_profile_shape_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_profile_shape_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_profile_shape_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ProfitFactor : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ProfitFactor(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_profit_factor_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ProfitFactor parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_profit_factor_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_profit_factor_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_profit_factor_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_profit_factor_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_profit_factor_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_profit_factor_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_profit_factor_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ProjectionBands : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ProjectionBands(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_projection_bands_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ProjectionBands parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_projection_bands_free);
|
|
}
|
|
|
|
public ProjectionBandsOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraProjectionBandsOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_projection_bands_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new ProjectionBandsOutput(native.upper, native.middle, native.lower) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_projection_bands_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_projection_bands_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_projection_bands_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_projection_bands_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ProjectionOscillator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ProjectionOscillator(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_projection_oscillator_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ProjectionOscillator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_projection_oscillator_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_projection_oscillator_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_projection_oscillator_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_projection_oscillator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_projection_oscillator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_projection_oscillator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_projection_oscillator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Psar : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Psar(double afStart, double afStep, double afMax)
|
|
{
|
|
var ptr = NativeMethods.wickra_psar_new(afStart, afStep, afMax);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Psar parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_psar_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_psar_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_psar_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_psar_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_psar_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_psar_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_psar_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Pvi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Pvi()
|
|
{
|
|
var ptr = NativeMethods.wickra_pvi_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Pvi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_pvi_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_pvi_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_pvi_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_pvi_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_pvi_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_pvi_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_pvi_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Qqe : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Qqe(int rsiPeriod, int smoothing, double factor)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(rsiPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(smoothing);
|
|
var ptr = NativeMethods.wickra_qqe_new((nuint)rsiPeriod, (nuint)smoothing, factor);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Qqe parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_qqe_free);
|
|
}
|
|
|
|
public QqeOutput? Update(double @value)
|
|
{
|
|
WickraQqeOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_qqe_update(_handle.DangerousGetHandle(), @value, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new QqeOutput(native.rsi_ma, native.trailing_line) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_qqe_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_qqe_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_qqe_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_qqe_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Qstick : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Qstick(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_qstick_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Qstick parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_qstick_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_qstick_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_qstick_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_qstick_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_qstick_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_qstick_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_qstick_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class QuartileBands : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public QuartileBands(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_quartile_bands_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid QuartileBands parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_quartile_bands_free);
|
|
}
|
|
|
|
public QuartileBandsOutput? Update(double @value)
|
|
{
|
|
WickraQuartileBandsOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_quartile_bands_update(_handle.DangerousGetHandle(), @value, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new QuartileBandsOutput(native.upper, native.middle, native.lower) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_quartile_bands_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_quartile_bands_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_quartile_bands_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_quartile_bands_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class QuotedSpread : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public QuotedSpread()
|
|
{
|
|
var ptr = NativeMethods.wickra_quoted_spread_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid QuotedSpread parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_quoted_spread_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> bidPrice, ReadOnlySpan<double> bidSize, ReadOnlySpan<double> askPrice, ReadOnlySpan<double> askSize)
|
|
{
|
|
if (bidSize.Length != bidPrice.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (askSize.Length != askPrice.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* bidPricePtr = bidPrice)
|
|
fixed (double* bidSizePtr = bidSize)
|
|
fixed (double* askPricePtr = askPrice)
|
|
fixed (double* askSizePtr = askSize)
|
|
{
|
|
result = NativeMethods.wickra_quoted_spread_update(_handle.DangerousGetHandle(), bidPricePtr, bidSizePtr, (nuint)bidPrice.Length, askPricePtr, askSizePtr, (nuint)askPrice.Length);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_quoted_spread_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_quoted_spread_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_quoted_spread_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_quoted_spread_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RSquared : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RSquared(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_r_squared_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RSquared parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_r_squared_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_r_squared_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_r_squared_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_r_squared_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_r_squared_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_r_squared_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_r_squared_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RangeBars : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RangeBars(double range)
|
|
{
|
|
var ptr = NativeMethods.wickra_range_bars_new(range);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RangeBars parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_range_bars_free);
|
|
}
|
|
|
|
public RangeBar[] Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
const int cap = 64;
|
|
Span<WickraRangeBar> buffer = stackalloc WickraRangeBar[cap];
|
|
long count;
|
|
unsafe
|
|
{
|
|
fixed (WickraRangeBar* ptr = buffer)
|
|
{
|
|
count = (long)NativeMethods.wickra_range_bars_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, ptr, (nuint)cap);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
if (count <= 0)
|
|
{
|
|
return Array.Empty<RangeBar>();
|
|
}
|
|
|
|
var result = new RangeBar[count];
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
result[i] = new RangeBar(buffer[i].open, buffer[i].close, buffer[i].direction);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_range_bars_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_range_bars_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RealizedSpread : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RealizedSpread(int horizon)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(horizon);
|
|
var ptr = NativeMethods.wickra_realized_spread_new((nuint)horizon);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RealizedSpread parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_realized_spread_free);
|
|
}
|
|
|
|
public double Update(double price, double size, bool isBuy, long timestamp, double mid)
|
|
{
|
|
var result = NativeMethods.wickra_realized_spread_update(_handle.DangerousGetHandle(), price, size, isBuy, timestamp, mid);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_realized_spread_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_realized_spread_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_realized_spread_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_realized_spread_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RealizedVolatility : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RealizedVolatility(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_realized_volatility_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RealizedVolatility parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_realized_volatility_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_realized_volatility_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_realized_volatility_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_realized_volatility_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_realized_volatility_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_realized_volatility_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_realized_volatility_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RecoveryFactor : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RecoveryFactor()
|
|
{
|
|
var ptr = NativeMethods.wickra_recovery_factor_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RecoveryFactor parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_recovery_factor_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_recovery_factor_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_recovery_factor_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_recovery_factor_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_recovery_factor_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_recovery_factor_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_recovery_factor_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RectangleRange : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RectangleRange()
|
|
{
|
|
var ptr = NativeMethods.wickra_rectangle_range_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RectangleRange parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rectangle_range_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_rectangle_range_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_rectangle_range_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rectangle_range_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rectangle_range_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rectangle_range_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rectangle_range_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Reflex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Reflex(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_reflex_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Reflex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_reflex_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_reflex_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_reflex_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_reflex_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_reflex_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_reflex_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_reflex_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RegimeLabel : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RegimeLabel(int volPeriod, int lookback)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(volPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(lookback);
|
|
var ptr = NativeMethods.wickra_regime_label_new((nuint)volPeriod, (nuint)lookback);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RegimeLabel parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_regime_label_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_regime_label_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_regime_label_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_regime_label_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_regime_label_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_regime_label_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_regime_label_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RelativeStrengthAB : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RelativeStrengthAB(int maPeriod, int rsiPeriod)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(maPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(rsiPeriod);
|
|
var ptr = NativeMethods.wickra_relative_strength_ab_new((nuint)maPeriod, (nuint)rsiPeriod);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RelativeStrengthAB parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_relative_strength_ab_free);
|
|
}
|
|
|
|
public RelativeStrengthOutput? Update(double x, double y)
|
|
{
|
|
WickraRelativeStrengthOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_relative_strength_ab_update(_handle.DangerousGetHandle(), x, y, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new RelativeStrengthOutput(native.ratio, native.ratio_ma, native.ratio_rsi) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_relative_strength_ab_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_relative_strength_ab_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_relative_strength_ab_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_relative_strength_ab_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RenkoBars : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RenkoBars(double boxSize)
|
|
{
|
|
var ptr = NativeMethods.wickra_renko_bars_new(boxSize);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RenkoBars parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_renko_bars_free);
|
|
}
|
|
|
|
public RenkoBrick[] Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
const int cap = 64;
|
|
Span<WickraRenkoBrick> buffer = stackalloc WickraRenkoBrick[cap];
|
|
long count;
|
|
unsafe
|
|
{
|
|
fixed (WickraRenkoBrick* ptr = buffer)
|
|
{
|
|
count = (long)NativeMethods.wickra_renko_bars_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, ptr, (nuint)cap);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
if (count <= 0)
|
|
{
|
|
return Array.Empty<RenkoBrick>();
|
|
}
|
|
|
|
var result = new RenkoBrick[count];
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
result[i] = new RenkoBrick(buffer[i].open, buffer[i].close, buffer[i].direction);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_renko_bars_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_renko_bars_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RenkoTrailingStop : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RenkoTrailingStop(double blockSize)
|
|
{
|
|
var ptr = NativeMethods.wickra_renko_trailing_stop_new(blockSize);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RenkoTrailingStop parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_renko_trailing_stop_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_renko_trailing_stop_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_renko_trailing_stop_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_renko_trailing_stop_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_renko_trailing_stop_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_renko_trailing_stop_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_renko_trailing_stop_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Resampler : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Resampler(long timeframe)
|
|
{
|
|
var ptr = NativeMethods.wickra_resampler_new(timeframe);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Resampler parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_resampler_free);
|
|
}
|
|
|
|
public Candle? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraCandle native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_resampler_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new Candle(native.open, native.high, native.low, native.close, native.volume, native.timestamp) : null;
|
|
}
|
|
|
|
/// <summary>Emit the final, still-open candle (null if none is pending).</summary>
|
|
public Candle? Flush()
|
|
{
|
|
WickraCandle native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_resampler_flush(_handle.DangerousGetHandle(), &native);
|
|
}
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new Candle(native.open, native.high, native.low, native.close, native.volume, native.timestamp) : null;
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RickshawMan : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RickshawMan()
|
|
{
|
|
var ptr = NativeMethods.wickra_rickshaw_man_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RickshawMan parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rickshaw_man_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_rickshaw_man_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_rickshaw_man_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rickshaw_man_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rickshaw_man_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rickshaw_man_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rickshaw_man_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RisingThreeMethods : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RisingThreeMethods()
|
|
{
|
|
var ptr = NativeMethods.wickra_rising_three_methods_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RisingThreeMethods parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rising_three_methods_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_rising_three_methods_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_rising_three_methods_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rising_three_methods_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rising_three_methods_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rising_three_methods_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rising_three_methods_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Rmi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Rmi(int period, int momentum)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(momentum);
|
|
var ptr = NativeMethods.wickra_rmi_new((nuint)period, (nuint)momentum);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Rmi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rmi_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_rmi_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_rmi_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rmi_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rmi_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rmi_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rmi_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Roc : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Roc(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_roc_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Roc parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_roc_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_roc_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_roc_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_roc_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_roc_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_roc_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_roc_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Rocp : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Rocp(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_rocp_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Rocp parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rocp_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_rocp_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_rocp_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rocp_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rocp_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rocp_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rocp_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Rocr : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Rocr(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_rocr_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Rocr parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rocr_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_rocr_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_rocr_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rocr_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rocr_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rocr_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rocr_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Rocr100 : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Rocr100(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_rocr100_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Rocr100 parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rocr100_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_rocr100_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_rocr100_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rocr100_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rocr100_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rocr100_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rocr100_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RogersSatchellVolatility : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RogersSatchellVolatility(int period, int tradingPeriods)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(tradingPeriods);
|
|
var ptr = NativeMethods.wickra_rogers_satchell_volatility_new((nuint)period, (nuint)tradingPeriods);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RogersSatchellVolatility parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rogers_satchell_volatility_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_rogers_satchell_volatility_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_rogers_satchell_volatility_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rogers_satchell_volatility_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rogers_satchell_volatility_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rogers_satchell_volatility_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rogers_satchell_volatility_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RollMeasure : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RollMeasure(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_roll_measure_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RollMeasure parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_roll_measure_free);
|
|
}
|
|
|
|
public double Update(double price, double size, bool isBuy, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_roll_measure_update(_handle.DangerousGetHandle(), price, size, isBuy, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_roll_measure_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_roll_measure_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_roll_measure_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_roll_measure_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RollingCorrelation : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RollingCorrelation(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_rolling_correlation_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RollingCorrelation parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rolling_correlation_free);
|
|
}
|
|
|
|
public double Update(double x, double y)
|
|
{
|
|
var result = NativeMethods.wickra_rolling_correlation_update(_handle.DangerousGetHandle(), x, y);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> x, ReadOnlySpan<double> y)
|
|
{
|
|
var n = x.Length;
|
|
if (y.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* xPtr = x)
|
|
fixed (double* yPtr = y)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_rolling_correlation_batch(_handle.DangerousGetHandle(), xPtr, yPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rolling_correlation_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rolling_correlation_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rolling_correlation_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rolling_correlation_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RollingCovariance : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RollingCovariance(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_rolling_covariance_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RollingCovariance parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rolling_covariance_free);
|
|
}
|
|
|
|
public double Update(double x, double y)
|
|
{
|
|
var result = NativeMethods.wickra_rolling_covariance_update(_handle.DangerousGetHandle(), x, y);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> x, ReadOnlySpan<double> y)
|
|
{
|
|
var n = x.Length;
|
|
if (y.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* xPtr = x)
|
|
fixed (double* yPtr = y)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_rolling_covariance_batch(_handle.DangerousGetHandle(), xPtr, yPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rolling_covariance_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rolling_covariance_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rolling_covariance_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rolling_covariance_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RollingIqr : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RollingIqr(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_rolling_iqr_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RollingIqr parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rolling_iqr_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_rolling_iqr_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_rolling_iqr_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rolling_iqr_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rolling_iqr_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rolling_iqr_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rolling_iqr_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RollingMinMaxScaler : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RollingMinMaxScaler(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_rolling_min_max_scaler_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RollingMinMaxScaler parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rolling_min_max_scaler_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_rolling_min_max_scaler_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_rolling_min_max_scaler_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rolling_min_max_scaler_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rolling_min_max_scaler_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rolling_min_max_scaler_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rolling_min_max_scaler_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RollingPercentileRank : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RollingPercentileRank(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_rolling_percentile_rank_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RollingPercentileRank parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rolling_percentile_rank_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_rolling_percentile_rank_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_rolling_percentile_rank_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rolling_percentile_rank_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rolling_percentile_rank_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rolling_percentile_rank_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rolling_percentile_rank_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RollingQuantile : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RollingQuantile(int period, double quantile)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_rolling_quantile_new((nuint)period, quantile);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RollingQuantile parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rolling_quantile_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_rolling_quantile_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_rolling_quantile_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rolling_quantile_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rolling_quantile_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rolling_quantile_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rolling_quantile_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RollingVwap : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RollingVwap(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_rolling_vwap_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RollingVwap parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rolling_vwap_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_rolling_vwap_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_rolling_vwap_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rolling_vwap_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rolling_vwap_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rolling_vwap_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rolling_vwap_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RoofingFilter : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RoofingFilter(int lpPeriod, int hpPeriod)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(lpPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(hpPeriod);
|
|
var ptr = NativeMethods.wickra_roofing_filter_new((nuint)lpPeriod, (nuint)hpPeriod);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RoofingFilter parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_roofing_filter_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_roofing_filter_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_roofing_filter_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_roofing_filter_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_roofing_filter_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_roofing_filter_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_roofing_filter_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Rsi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Rsi(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_rsi_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Rsi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rsi_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_rsi_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_rsi_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rsi_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rsi_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rsi_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rsi_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Rsx : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Rsx(int length)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(length);
|
|
var ptr = NativeMethods.wickra_rsx_new((nuint)length);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Rsx parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rsx_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_rsx_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_rsx_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rsx_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rsx_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rsx_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rsx_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RunBars : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RunBars(int runLength)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(runLength);
|
|
var ptr = NativeMethods.wickra_run_bars_new((nuint)runLength);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RunBars parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_run_bars_free);
|
|
}
|
|
|
|
public RunBar[] Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
const int cap = 64;
|
|
Span<WickraRunBar> buffer = stackalloc WickraRunBar[cap];
|
|
long count;
|
|
unsafe
|
|
{
|
|
fixed (WickraRunBar* ptr = buffer)
|
|
{
|
|
count = (long)NativeMethods.wickra_run_bars_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, ptr, (nuint)cap);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
if (count <= 0)
|
|
{
|
|
return Array.Empty<RunBar>();
|
|
}
|
|
|
|
var result = new RunBar[count];
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
result[i] = new RunBar(buffer[i].open, buffer[i].high, buffer[i].low, buffer[i].close, buffer[i].length, buffer[i].direction);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_run_bars_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_run_bars_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Rvi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Rvi(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_rvi_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Rvi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rvi_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_rvi_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_rvi_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rvi_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rvi_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rvi_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rvi_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class RviVolatility : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public RviVolatility(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_rvi_volatility_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid RviVolatility parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rvi_volatility_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_rvi_volatility_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_rvi_volatility_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rvi_volatility_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rvi_volatility_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rvi_volatility_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rvi_volatility_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Rwi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Rwi(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_rwi_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Rwi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_rwi_free);
|
|
}
|
|
|
|
public RwiOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraRwiOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_rwi_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new RwiOutput(native.high, native.low) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_rwi_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_rwi_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_rwi_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_rwi_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SampleEntropy : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SampleEntropy(int period, int m, double rFactor)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(m);
|
|
var ptr = NativeMethods.wickra_sample_entropy_new((nuint)period, (nuint)m, rFactor);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SampleEntropy parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_sample_entropy_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_sample_entropy_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_sample_entropy_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_sample_entropy_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_sample_entropy_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_sample_entropy_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_sample_entropy_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SarExt : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SarExt(double startValue, double offsetOnReverse, double accelInitLong, double accelLong, double accelMaxLong, double accelInitShort, double accelShort, double accelMaxShort)
|
|
{
|
|
var ptr = NativeMethods.wickra_sar_ext_new(startValue, offsetOnReverse, accelInitLong, accelLong, accelMaxLong, accelInitShort, accelShort, accelMaxShort);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SarExt parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_sar_ext_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_sar_ext_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_sar_ext_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_sar_ext_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_sar_ext_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_sar_ext_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_sar_ext_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SeasonalZScore : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SeasonalZScore(int utcOffsetMinutes)
|
|
{
|
|
var ptr = NativeMethods.wickra_seasonal_z_score_new(utcOffsetMinutes);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SeasonalZScore parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_seasonal_z_score_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_seasonal_z_score_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_seasonal_z_score_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_seasonal_z_score_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_seasonal_z_score_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_seasonal_z_score_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_seasonal_z_score_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SeparatingLines : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SeparatingLines()
|
|
{
|
|
var ptr = NativeMethods.wickra_separating_lines_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SeparatingLines parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_separating_lines_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_separating_lines_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_separating_lines_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_separating_lines_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_separating_lines_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_separating_lines_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_separating_lines_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SessionHighLow : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SessionHighLow(int utcOffsetMinutes)
|
|
{
|
|
var ptr = NativeMethods.wickra_session_high_low_new(utcOffsetMinutes);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SessionHighLow parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_session_high_low_free);
|
|
}
|
|
|
|
public SessionHighLowOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraSessionHighLowOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_session_high_low_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new SessionHighLowOutput(native.high, native.low) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_session_high_low_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_session_high_low_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_session_high_low_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_session_high_low_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SessionRange : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SessionRange(int utcOffsetMinutes)
|
|
{
|
|
var ptr = NativeMethods.wickra_session_range_new(utcOffsetMinutes);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SessionRange parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_session_range_free);
|
|
}
|
|
|
|
public SessionRangeOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraSessionRangeOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_session_range_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new SessionRangeOutput(native.asia, native.eu, native.us) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_session_range_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_session_range_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_session_range_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_session_range_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SessionVwap : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SessionVwap(int utcOffsetMinutes)
|
|
{
|
|
var ptr = NativeMethods.wickra_session_vwap_new(utcOffsetMinutes);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SessionVwap parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_session_vwap_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_session_vwap_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_session_vwap_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_session_vwap_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_session_vwap_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_session_vwap_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_session_vwap_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ShannonEntropy : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ShannonEntropy(int period, int bins)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(bins);
|
|
var ptr = NativeMethods.wickra_shannon_entropy_new((nuint)period, (nuint)bins);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ShannonEntropy parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_shannon_entropy_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_shannon_entropy_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_shannon_entropy_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_shannon_entropy_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_shannon_entropy_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_shannon_entropy_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_shannon_entropy_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Shark : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Shark()
|
|
{
|
|
var ptr = NativeMethods.wickra_shark_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Shark parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_shark_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_shark_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_shark_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_shark_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_shark_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_shark_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_shark_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SharpeRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SharpeRatio(int period, double riskFree)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_sharpe_ratio_new((nuint)period, riskFree);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SharpeRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_sharpe_ratio_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_sharpe_ratio_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_sharpe_ratio_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_sharpe_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_sharpe_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_sharpe_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_sharpe_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ShootingStar : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ShootingStar()
|
|
{
|
|
var ptr = NativeMethods.wickra_shooting_star_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ShootingStar parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_shooting_star_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_shooting_star_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_shooting_star_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_shooting_star_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_shooting_star_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_shooting_star_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_shooting_star_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ShortLine : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ShortLine()
|
|
{
|
|
var ptr = NativeMethods.wickra_short_line_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ShortLine parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_short_line_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_short_line_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_short_line_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_short_line_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_short_line_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_short_line_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_short_line_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SignedVolume : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SignedVolume()
|
|
{
|
|
var ptr = NativeMethods.wickra_signed_volume_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SignedVolume parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_signed_volume_free);
|
|
}
|
|
|
|
public double Update(double price, double size, bool isBuy, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_signed_volume_update(_handle.DangerousGetHandle(), price, size, isBuy, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_signed_volume_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_signed_volume_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_signed_volume_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_signed_volume_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SineWave : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SineWave()
|
|
{
|
|
var ptr = NativeMethods.wickra_sine_wave_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SineWave parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_sine_wave_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_sine_wave_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_sine_wave_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_sine_wave_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_sine_wave_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_sine_wave_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_sine_wave_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SineWeightedMa : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SineWeightedMa(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_sine_weighted_ma_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SineWeightedMa parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_sine_weighted_ma_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_sine_weighted_ma_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_sine_weighted_ma_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_sine_weighted_ma_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_sine_weighted_ma_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_sine_weighted_ma_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_sine_weighted_ma_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SinglePrints : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SinglePrints(int period, int bins)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(bins);
|
|
var ptr = NativeMethods.wickra_single_prints_new((nuint)period, (nuint)bins);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SinglePrints parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_single_prints_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_single_prints_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_single_prints_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_single_prints_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_single_prints_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_single_prints_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_single_prints_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Skewness : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Skewness(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_skewness_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Skewness parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_skewness_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_skewness_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_skewness_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_skewness_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_skewness_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_skewness_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_skewness_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Sma : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Sma(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_sma_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Sma parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_sma_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_sma_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_sma_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_sma_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_sma_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_sma_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_sma_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Smi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Smi(int period, int dPeriod, int d2Period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(dPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(d2Period);
|
|
var ptr = NativeMethods.wickra_smi_new((nuint)period, (nuint)dPeriod, (nuint)d2Period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Smi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_smi_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_smi_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_smi_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_smi_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_smi_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_smi_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_smi_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Smma : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Smma(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_smma_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Smma parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_smma_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_smma_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_smma_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_smma_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_smma_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_smma_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_smma_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SmoothedHeikinAshi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SmoothedHeikinAshi(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_smoothed_heikin_ashi_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SmoothedHeikinAshi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_smoothed_heikin_ashi_free);
|
|
}
|
|
|
|
public SmoothedHeikinAshiOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraSmoothedHeikinAshiOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_smoothed_heikin_ashi_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new SmoothedHeikinAshiOutput(native.open, native.high, native.low, native.close) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_smoothed_heikin_ashi_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_smoothed_heikin_ashi_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_smoothed_heikin_ashi_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_smoothed_heikin_ashi_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SortinoRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SortinoRatio(int period, double mar)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_sortino_ratio_new((nuint)period, mar);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SortinoRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_sortino_ratio_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_sortino_ratio_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_sortino_ratio_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_sortino_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_sortino_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_sortino_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_sortino_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SpearmanCorrelation : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SpearmanCorrelation(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_spearman_correlation_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SpearmanCorrelation parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_spearman_correlation_free);
|
|
}
|
|
|
|
public double Update(double x, double y)
|
|
{
|
|
var result = NativeMethods.wickra_spearman_correlation_update(_handle.DangerousGetHandle(), x, y);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> x, ReadOnlySpan<double> y)
|
|
{
|
|
var n = x.Length;
|
|
if (y.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* xPtr = x)
|
|
fixed (double* yPtr = y)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_spearman_correlation_batch(_handle.DangerousGetHandle(), xPtr, yPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_spearman_correlation_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_spearman_correlation_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_spearman_correlation_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_spearman_correlation_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SpinningTop : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SpinningTop()
|
|
{
|
|
var ptr = NativeMethods.wickra_spinning_top_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SpinningTop parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_spinning_top_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_spinning_top_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_spinning_top_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_spinning_top_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_spinning_top_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_spinning_top_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_spinning_top_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SpreadAr1Coefficient : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SpreadAr1Coefficient(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_spread_ar1_coefficient_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SpreadAr1Coefficient parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_spread_ar1_coefficient_free);
|
|
}
|
|
|
|
public double Update(double x, double y)
|
|
{
|
|
var result = NativeMethods.wickra_spread_ar1_coefficient_update(_handle.DangerousGetHandle(), x, y);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> x, ReadOnlySpan<double> y)
|
|
{
|
|
var n = x.Length;
|
|
if (y.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* xPtr = x)
|
|
fixed (double* yPtr = y)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_spread_ar1_coefficient_batch(_handle.DangerousGetHandle(), xPtr, yPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_spread_ar1_coefficient_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_spread_ar1_coefficient_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_spread_ar1_coefficient_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_spread_ar1_coefficient_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SpreadBollingerBands : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SpreadBollingerBands(int period, double numStd)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_spread_bollinger_bands_new((nuint)period, numStd);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SpreadBollingerBands parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_spread_bollinger_bands_free);
|
|
}
|
|
|
|
public SpreadBollingerBandsOutput? Update(double x, double y)
|
|
{
|
|
WickraSpreadBollingerBandsOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_spread_bollinger_bands_update(_handle.DangerousGetHandle(), x, y, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new SpreadBollingerBandsOutput(native.middle, native.upper, native.lower, native.percent_b) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_spread_bollinger_bands_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_spread_bollinger_bands_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_spread_bollinger_bands_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_spread_bollinger_bands_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SpreadHurst : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SpreadHurst(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_spread_hurst_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SpreadHurst parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_spread_hurst_free);
|
|
}
|
|
|
|
public double Update(double x, double y)
|
|
{
|
|
var result = NativeMethods.wickra_spread_hurst_update(_handle.DangerousGetHandle(), x, y);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> x, ReadOnlySpan<double> y)
|
|
{
|
|
var n = x.Length;
|
|
if (y.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* xPtr = x)
|
|
fixed (double* yPtr = y)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_spread_hurst_batch(_handle.DangerousGetHandle(), xPtr, yPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_spread_hurst_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_spread_hurst_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_spread_hurst_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_spread_hurst_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class StalledPattern : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public StalledPattern()
|
|
{
|
|
var ptr = NativeMethods.wickra_stalled_pattern_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid StalledPattern parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_stalled_pattern_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_stalled_pattern_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_stalled_pattern_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_stalled_pattern_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_stalled_pattern_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_stalled_pattern_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_stalled_pattern_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class StandardError : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public StandardError(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_standard_error_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid StandardError parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_standard_error_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_standard_error_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_standard_error_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_standard_error_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_standard_error_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_standard_error_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_standard_error_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class StandardErrorBands : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public StandardErrorBands(int period, double multiplier)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_standard_error_bands_new((nuint)period, multiplier);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid StandardErrorBands parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_standard_error_bands_free);
|
|
}
|
|
|
|
public StandardErrorBandsOutput? Update(double @value)
|
|
{
|
|
WickraStandardErrorBandsOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_standard_error_bands_update(_handle.DangerousGetHandle(), @value, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new StandardErrorBandsOutput(native.upper, native.middle, native.lower) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_standard_error_bands_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_standard_error_bands_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_standard_error_bands_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_standard_error_bands_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class StarcBands : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public StarcBands(int smaPeriod, int atrPeriod, double multiplier)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(smaPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(atrPeriod);
|
|
var ptr = NativeMethods.wickra_starc_bands_new((nuint)smaPeriod, (nuint)atrPeriod, multiplier);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid StarcBands parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_starc_bands_free);
|
|
}
|
|
|
|
public StarcBandsOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraStarcBandsOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_starc_bands_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new StarcBandsOutput(native.upper, native.middle, native.lower) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_starc_bands_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_starc_bands_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_starc_bands_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_starc_bands_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Stc : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Stc(int fast, int slow, int schaffPeriod, double factor)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(fast);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(slow);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(schaffPeriod);
|
|
var ptr = NativeMethods.wickra_stc_new((nuint)fast, (nuint)slow, (nuint)schaffPeriod, factor);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Stc parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_stc_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_stc_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_stc_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_stc_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_stc_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_stc_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_stc_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class StdDev : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public StdDev(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_std_dev_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid StdDev parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_std_dev_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_std_dev_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_std_dev_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_std_dev_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_std_dev_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_std_dev_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_std_dev_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class StepTrailingStop : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public StepTrailingStop(double stepSize)
|
|
{
|
|
var ptr = NativeMethods.wickra_step_trailing_stop_new(stepSize);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid StepTrailingStop parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_step_trailing_stop_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_step_trailing_stop_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_step_trailing_stop_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_step_trailing_stop_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_step_trailing_stop_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_step_trailing_stop_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_step_trailing_stop_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SterlingRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SterlingRatio(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_sterling_ratio_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SterlingRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_sterling_ratio_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_sterling_ratio_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_sterling_ratio_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_sterling_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_sterling_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_sterling_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_sterling_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class StickSandwich : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public StickSandwich()
|
|
{
|
|
var ptr = NativeMethods.wickra_stick_sandwich_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid StickSandwich parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_stick_sandwich_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_stick_sandwich_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_stick_sandwich_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_stick_sandwich_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_stick_sandwich_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_stick_sandwich_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_stick_sandwich_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class StochRsi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public StochRsi(int rsiPeriod, int stochPeriod)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(rsiPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(stochPeriod);
|
|
var ptr = NativeMethods.wickra_stoch_rsi_new((nuint)rsiPeriod, (nuint)stochPeriod);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid StochRsi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_stoch_rsi_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_stoch_rsi_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_stoch_rsi_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_stoch_rsi_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_stoch_rsi_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_stoch_rsi_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_stoch_rsi_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Stochastic : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Stochastic(int kPeriod, int dPeriod)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(kPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(dPeriod);
|
|
var ptr = NativeMethods.wickra_stochastic_new((nuint)kPeriod, (nuint)dPeriod);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Stochastic parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_stochastic_free);
|
|
}
|
|
|
|
public StochasticOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraStochasticOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_stochastic_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new StochasticOutput(native.k, native.d) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_stochastic_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_stochastic_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_stochastic_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_stochastic_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class StochasticCci : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public StochasticCci(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_stochastic_cci_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid StochasticCci parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_stochastic_cci_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_stochastic_cci_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_stochastic_cci_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_stochastic_cci_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_stochastic_cci_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_stochastic_cci_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_stochastic_cci_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SuperSmoother : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SuperSmoother(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_super_smoother_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SuperSmoother parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_super_smoother_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_super_smoother_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_super_smoother_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_super_smoother_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_super_smoother_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_super_smoother_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_super_smoother_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class SuperTrend : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public SuperTrend(int atrPeriod, double multiplier)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(atrPeriod);
|
|
var ptr = NativeMethods.wickra_super_trend_new((nuint)atrPeriod, multiplier);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid SuperTrend parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_super_trend_free);
|
|
}
|
|
|
|
public SuperTrendOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraSuperTrendOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_super_trend_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new SuperTrendOutput(native.@value, native.direction) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_super_trend_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_super_trend_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_super_trend_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_super_trend_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class T3 : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public T3(int period, double v)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_t3_new((nuint)period, v);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid T3 parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_t3_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_t3_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_t3_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_t3_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_t3_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_t3_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_t3_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TailRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TailRatio(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_tail_ratio_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TailRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_tail_ratio_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_tail_ratio_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_tail_ratio_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_tail_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_tail_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_tail_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_tail_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TakerBuySellRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TakerBuySellRatio()
|
|
{
|
|
var ptr = NativeMethods.wickra_taker_buy_sell_ratio_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TakerBuySellRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_taker_buy_sell_ratio_free);
|
|
}
|
|
|
|
public double Update(double fundingRate, double markPrice, double indexPrice, double futuresPrice, double openInterest, double longSize, double shortSize, double takerBuyVolume, double takerSellVolume, double longLiquidation, double shortLiquidation, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_taker_buy_sell_ratio_update(_handle.DangerousGetHandle(), fundingRate, markPrice, indexPrice, futuresPrice, openInterest, longSize, shortSize, takerBuyVolume, takerSellVolume, longLiquidation, shortLiquidation, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_taker_buy_sell_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_taker_buy_sell_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_taker_buy_sell_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_taker_buy_sell_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Takuri : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Takuri()
|
|
{
|
|
var ptr = NativeMethods.wickra_takuri_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Takuri parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_takuri_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_takuri_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_takuri_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_takuri_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_takuri_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_takuri_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_takuri_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TasukiGap : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TasukiGap()
|
|
{
|
|
var ptr = NativeMethods.wickra_tasuki_gap_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TasukiGap parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_tasuki_gap_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_tasuki_gap_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_tasuki_gap_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_tasuki_gap_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_tasuki_gap_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_tasuki_gap_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_tasuki_gap_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TdCamouflage : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TdCamouflage()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_camouflage_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TdCamouflage parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_td_camouflage_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_td_camouflage_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_td_camouflage_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_td_camouflage_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_td_camouflage_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_camouflage_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_td_camouflage_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TdClop : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TdClop()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_clop_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TdClop parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_td_clop_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_td_clop_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_td_clop_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_td_clop_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_td_clop_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_clop_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_td_clop_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TdClopwin : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TdClopwin()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_clopwin_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TdClopwin parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_td_clopwin_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_td_clopwin_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_td_clopwin_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_td_clopwin_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_td_clopwin_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_clopwin_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_td_clopwin_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TdCombo : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TdCombo(int setupLookback, int setupTarget, int countdownLookback, int countdownTarget)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(setupLookback);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(setupTarget);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(countdownLookback);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(countdownTarget);
|
|
var ptr = NativeMethods.wickra_td_combo_new((nuint)setupLookback, (nuint)setupTarget, (nuint)countdownLookback, (nuint)countdownTarget);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TdCombo parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_td_combo_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_td_combo_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_td_combo_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_td_combo_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_td_combo_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_combo_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_td_combo_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TdCountdown : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TdCountdown(int setupLookback, int setupTarget, int countdownLookback, int countdownTarget)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(setupLookback);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(setupTarget);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(countdownLookback);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(countdownTarget);
|
|
var ptr = NativeMethods.wickra_td_countdown_new((nuint)setupLookback, (nuint)setupTarget, (nuint)countdownLookback, (nuint)countdownTarget);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TdCountdown parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_td_countdown_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_td_countdown_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_td_countdown_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_td_countdown_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_td_countdown_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_countdown_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_td_countdown_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TdDWave : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TdDWave(int strength)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(strength);
|
|
var ptr = NativeMethods.wickra_td_d_wave_new((nuint)strength);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TdDWave parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_td_d_wave_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_td_d_wave_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_td_d_wave_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_td_d_wave_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_td_d_wave_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_d_wave_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_td_d_wave_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TdDeMarker : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TdDeMarker(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_td_de_marker_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TdDeMarker parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_td_de_marker_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_td_de_marker_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_td_de_marker_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_td_de_marker_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_td_de_marker_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_de_marker_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_td_de_marker_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TdDifferential : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TdDifferential()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_differential_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TdDifferential parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_td_differential_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_td_differential_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_td_differential_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_td_differential_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_td_differential_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_differential_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_td_differential_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TdLines : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TdLines(int lookback, int target)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(lookback);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(target);
|
|
var ptr = NativeMethods.wickra_td_lines_new((nuint)lookback, (nuint)target);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TdLines parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_td_lines_free);
|
|
}
|
|
|
|
public TdLinesOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraTdLinesOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_td_lines_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new TdLinesOutput(native.resistance, native.support) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_td_lines_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_td_lines_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_lines_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_td_lines_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TdMovingAverage : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TdMovingAverage(int periodSt1, int periodSt2)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(periodSt1);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(periodSt2);
|
|
var ptr = NativeMethods.wickra_td_moving_average_new((nuint)periodSt1, (nuint)periodSt2);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TdMovingAverage parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_td_moving_average_free);
|
|
}
|
|
|
|
public TdMovingAverageOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraTdMovingAverageOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_td_moving_average_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new TdMovingAverageOutput(native.st1, native.st2) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_td_moving_average_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_td_moving_average_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_moving_average_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_td_moving_average_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TdOpen : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TdOpen()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_open_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TdOpen parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_td_open_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_td_open_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_td_open_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_td_open_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_td_open_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_open_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_td_open_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TdPressure : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TdPressure(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_td_pressure_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TdPressure parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_td_pressure_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_td_pressure_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_td_pressure_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_td_pressure_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_td_pressure_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_pressure_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_td_pressure_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TdPropulsion : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TdPropulsion()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_propulsion_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TdPropulsion parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_td_propulsion_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_td_propulsion_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_td_propulsion_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_td_propulsion_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_td_propulsion_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_propulsion_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_td_propulsion_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TdRangeProjection : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TdRangeProjection()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_range_projection_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TdRangeProjection parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_td_range_projection_free);
|
|
}
|
|
|
|
public TdRangeProjectionOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraTdRangeProjectionOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_td_range_projection_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new TdRangeProjectionOutput(native.high, native.low) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_td_range_projection_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_td_range_projection_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_range_projection_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_td_range_projection_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TdRei : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TdRei(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_td_rei_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TdRei parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_td_rei_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_td_rei_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_td_rei_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_td_rei_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_td_rei_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_rei_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_td_rei_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TdRiskLevel : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TdRiskLevel(int lookback, int target)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(lookback);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(target);
|
|
var ptr = NativeMethods.wickra_td_risk_level_new((nuint)lookback, (nuint)target);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TdRiskLevel parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_td_risk_level_free);
|
|
}
|
|
|
|
public TdRiskLevelOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraTdRiskLevelOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_td_risk_level_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new TdRiskLevelOutput(native.buy_risk, native.sell_risk) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_td_risk_level_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_td_risk_level_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_risk_level_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_td_risk_level_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TdSequential : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TdSequential(int setupLookback, int setupTarget, int countdownLookback, int countdownTarget)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(setupLookback);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(setupTarget);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(countdownLookback);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(countdownTarget);
|
|
var ptr = NativeMethods.wickra_td_sequential_new((nuint)setupLookback, (nuint)setupTarget, (nuint)countdownLookback, (nuint)countdownTarget);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TdSequential parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_td_sequential_free);
|
|
}
|
|
|
|
public TdSequentialOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraTdSequentialOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_td_sequential_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new TdSequentialOutput(native.setup, native.countdown, native.direction) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_td_sequential_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_td_sequential_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_sequential_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_td_sequential_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TdSetup : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TdSetup(int lookback, int target)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(lookback);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(target);
|
|
var ptr = NativeMethods.wickra_td_setup_new((nuint)lookback, (nuint)target);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TdSetup parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_td_setup_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_td_setup_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_td_setup_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_td_setup_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_td_setup_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_setup_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_td_setup_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TdTrap : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TdTrap()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_trap_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TdTrap parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_td_trap_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_td_trap_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_td_trap_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_td_trap_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_td_trap_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_td_trap_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_td_trap_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Tema : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Tema(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_tema_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Tema parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_tema_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_tema_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_tema_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_tema_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_tema_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_tema_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_tema_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TermStructureBasis : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TermStructureBasis()
|
|
{
|
|
var ptr = NativeMethods.wickra_term_structure_basis_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TermStructureBasis parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_term_structure_basis_free);
|
|
}
|
|
|
|
public double Update(double fundingRate, double markPrice, double indexPrice, double futuresPrice, double openInterest, double longSize, double shortSize, double takerBuyVolume, double takerSellVolume, double longLiquidation, double shortLiquidation, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_term_structure_basis_update(_handle.DangerousGetHandle(), fundingRate, markPrice, indexPrice, futuresPrice, openInterest, longSize, shortSize, takerBuyVolume, takerSellVolume, longLiquidation, shortLiquidation, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_term_structure_basis_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_term_structure_basis_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_term_structure_basis_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_term_structure_basis_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ThreeDrives : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ThreeDrives()
|
|
{
|
|
var ptr = NativeMethods.wickra_three_drives_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ThreeDrives parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_three_drives_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_three_drives_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_three_drives_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_three_drives_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_three_drives_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_three_drives_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_three_drives_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ThreeInside : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ThreeInside()
|
|
{
|
|
var ptr = NativeMethods.wickra_three_inside_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ThreeInside parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_three_inside_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_three_inside_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_three_inside_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_three_inside_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_three_inside_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_three_inside_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_three_inside_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ThreeLineBreak : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ThreeLineBreak(int lines)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(lines);
|
|
var ptr = NativeMethods.wickra_three_line_break_new((nuint)lines);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ThreeLineBreak parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_three_line_break_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_three_line_break_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_three_line_break_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_three_line_break_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_three_line_break_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_three_line_break_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_three_line_break_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ThreeLineBreakBars : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ThreeLineBreakBars(int lines)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(lines);
|
|
var ptr = NativeMethods.wickra_three_line_break_bars_new((nuint)lines);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ThreeLineBreakBars parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_three_line_break_bars_free);
|
|
}
|
|
|
|
public LineBreakBar[] Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
const int cap = 64;
|
|
Span<WickraLineBreakBar> buffer = stackalloc WickraLineBreakBar[cap];
|
|
long count;
|
|
unsafe
|
|
{
|
|
fixed (WickraLineBreakBar* ptr = buffer)
|
|
{
|
|
count = (long)NativeMethods.wickra_three_line_break_bars_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, ptr, (nuint)cap);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
if (count <= 0)
|
|
{
|
|
return Array.Empty<LineBreakBar>();
|
|
}
|
|
|
|
var result = new LineBreakBar[count];
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
result[i] = new LineBreakBar(buffer[i].open, buffer[i].close, buffer[i].direction);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_three_line_break_bars_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_three_line_break_bars_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ThreeLineStrike : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ThreeLineStrike()
|
|
{
|
|
var ptr = NativeMethods.wickra_three_line_strike_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ThreeLineStrike parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_three_line_strike_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_three_line_strike_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_three_line_strike_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_three_line_strike_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_three_line_strike_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_three_line_strike_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_three_line_strike_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ThreeOutside : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ThreeOutside()
|
|
{
|
|
var ptr = NativeMethods.wickra_three_outside_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ThreeOutside parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_three_outside_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_three_outside_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_three_outside_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_three_outside_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_three_outside_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_three_outside_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_three_outside_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ThreeSoldiersOrCrows : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ThreeSoldiersOrCrows()
|
|
{
|
|
var ptr = NativeMethods.wickra_three_soldiers_or_crows_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ThreeSoldiersOrCrows parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_three_soldiers_or_crows_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_three_soldiers_or_crows_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_three_soldiers_or_crows_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_three_soldiers_or_crows_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_three_soldiers_or_crows_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_three_soldiers_or_crows_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_three_soldiers_or_crows_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ThreeStarsInSouth : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ThreeStarsInSouth()
|
|
{
|
|
var ptr = NativeMethods.wickra_three_stars_in_south_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ThreeStarsInSouth parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_three_stars_in_south_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_three_stars_in_south_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_three_stars_in_south_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_three_stars_in_south_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_three_stars_in_south_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_three_stars_in_south_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_three_stars_in_south_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Thrusting : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Thrusting()
|
|
{
|
|
var ptr = NativeMethods.wickra_thrusting_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Thrusting parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_thrusting_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_thrusting_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_thrusting_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_thrusting_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_thrusting_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_thrusting_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_thrusting_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TickAggregator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TickAggregator(long bucket, bool gapFill)
|
|
{
|
|
var ptr = NativeMethods.wickra_tick_aggregator_new(bucket, gapFill);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TickAggregator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_tick_aggregator_free);
|
|
}
|
|
|
|
|
|
/// <summary>Feed one trade tick; returns the candles it closed.</summary>
|
|
public Candle[] Push(double price, double size, long timestamp)
|
|
{
|
|
var count = (long)NativeMethods.wickra_tick_aggregator_push(_handle.DangerousGetHandle(), price, size, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
if (count <= 0)
|
|
{
|
|
return Array.Empty<Candle>();
|
|
}
|
|
var buffer = new WickraCandle[count];
|
|
unsafe
|
|
{
|
|
fixed (WickraCandle* ptr = buffer)
|
|
{
|
|
NativeMethods.wickra_tick_aggregator_drain(_handle.DangerousGetHandle(), ptr, (nuint)count);
|
|
}
|
|
}
|
|
GC.KeepAlive(_handle);
|
|
var result = new Candle[count];
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
result[i] = new Candle(buffer[i].open, buffer[i].high, buffer[i].low, buffer[i].close, buffer[i].volume, buffer[i].timestamp);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TickBars : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TickBars(int ticks)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(ticks);
|
|
var ptr = NativeMethods.wickra_tick_bars_new((nuint)ticks);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TickBars parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_tick_bars_free);
|
|
}
|
|
|
|
public TickBar[] Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
const int cap = 64;
|
|
Span<WickraTickBar> buffer = stackalloc WickraTickBar[cap];
|
|
long count;
|
|
unsafe
|
|
{
|
|
fixed (WickraTickBar* ptr = buffer)
|
|
{
|
|
count = (long)NativeMethods.wickra_tick_bars_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, ptr, (nuint)cap);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
if (count <= 0)
|
|
{
|
|
return Array.Empty<TickBar>();
|
|
}
|
|
|
|
var result = new TickBar[count];
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
result[i] = new TickBar(buffer[i].open, buffer[i].high, buffer[i].low, buffer[i].close, buffer[i].volume);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_tick_bars_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_tick_bars_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TickIndex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TickIndex()
|
|
{
|
|
var ptr = NativeMethods.wickra_tick_index_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TickIndex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_tick_index_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> change, ReadOnlySpan<double> volume, ReadOnlySpan<bool> newHigh, ReadOnlySpan<bool> newLow, ReadOnlySpan<bool> aboveMa, ReadOnlySpan<bool> onBuySignal, long timestamp)
|
|
{
|
|
if (volume.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newHigh.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newLow.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (aboveMa.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (onBuySignal.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* changePtr = change)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (bool* newHighPtr = newHigh)
|
|
fixed (bool* newLowPtr = newLow)
|
|
fixed (bool* aboveMaPtr = aboveMa)
|
|
fixed (bool* onBuySignalPtr = onBuySignal)
|
|
{
|
|
result = NativeMethods.wickra_tick_index_update(_handle.DangerousGetHandle(), changePtr, volumePtr, newHighPtr, newLowPtr, aboveMaPtr, onBuySignalPtr, (nuint)change.Length, timestamp);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_tick_index_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_tick_index_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_tick_index_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_tick_index_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Tii : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Tii(int smaPeriod, int devPeriod)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(smaPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(devPeriod);
|
|
var ptr = NativeMethods.wickra_tii_new((nuint)smaPeriod, (nuint)devPeriod);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Tii parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_tii_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_tii_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_tii_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_tii_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_tii_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_tii_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_tii_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TimeBasedStop : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TimeBasedStop(int maxBars)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(maxBars);
|
|
var ptr = NativeMethods.wickra_time_based_stop_new((nuint)maxBars);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TimeBasedStop parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_time_based_stop_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_time_based_stop_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_time_based_stop_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_time_based_stop_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_time_based_stop_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_time_based_stop_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_time_based_stop_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TimeOfDayReturnProfile : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
private readonly int _valuesCapacity;
|
|
|
|
public TimeOfDayReturnProfile(int buckets, int utcOffsetMinutes)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(buckets);
|
|
var ptr = NativeMethods.wickra_time_of_day_return_profile_new((nuint)buckets, utcOffsetMinutes);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TimeOfDayReturnProfile parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_time_of_day_return_profile_free);
|
|
_valuesCapacity = buckets;
|
|
}
|
|
|
|
public double[]? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var values = new double[_valuesCapacity];
|
|
long length;
|
|
unsafe
|
|
{
|
|
fixed (double* valuesPtr = values)
|
|
{
|
|
length = (long)NativeMethods.wickra_time_of_day_return_profile_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, valuesPtr, (nuint)_valuesCapacity);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
if (length < 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (length < values.Length)
|
|
{
|
|
Array.Resize(ref values, (int)length);
|
|
}
|
|
|
|
return values;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_time_of_day_return_profile_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_time_of_day_return_profile_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_time_of_day_return_profile_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_time_of_day_return_profile_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TowerTopBottom : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TowerTopBottom()
|
|
{
|
|
var ptr = NativeMethods.wickra_tower_top_bottom_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TowerTopBottom parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_tower_top_bottom_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_tower_top_bottom_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_tower_top_bottom_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_tower_top_bottom_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_tower_top_bottom_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_tower_top_bottom_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_tower_top_bottom_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TpoProfile : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
private readonly int _valuesCapacity;
|
|
|
|
public TpoProfile(int period, int binCount)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(binCount);
|
|
var ptr = NativeMethods.wickra_tpo_profile_new((nuint)period, (nuint)binCount);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TpoProfile parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_tpo_profile_free);
|
|
_valuesCapacity = binCount;
|
|
}
|
|
|
|
public TpoProfileOutputScalars? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var values = new double[_valuesCapacity];
|
|
WickraTpoProfileOutputScalars scalars;
|
|
long length;
|
|
unsafe
|
|
{
|
|
fixed (double* valuesPtr = values)
|
|
{
|
|
length = (long)NativeMethods.wickra_tpo_profile_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &scalars, valuesPtr, (nuint)_valuesCapacity);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
if (length < 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (length < values.Length)
|
|
{
|
|
Array.Resize(ref values, (int)length);
|
|
}
|
|
|
|
return new TpoProfileOutputScalars(scalars.price_low, scalars.price_high, values);
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_tpo_profile_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_tpo_profile_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_tpo_profile_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_tpo_profile_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TradeImbalance : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TradeImbalance(int window)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(window);
|
|
var ptr = NativeMethods.wickra_trade_imbalance_new((nuint)window);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TradeImbalance parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_trade_imbalance_free);
|
|
}
|
|
|
|
public double Update(double price, double size, bool isBuy, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_trade_imbalance_update(_handle.DangerousGetHandle(), price, size, isBuy, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_trade_imbalance_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_trade_imbalance_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_trade_imbalance_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_trade_imbalance_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TradeSignAutocorrelation : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TradeSignAutocorrelation(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_trade_sign_autocorrelation_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TradeSignAutocorrelation parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_trade_sign_autocorrelation_free);
|
|
}
|
|
|
|
public double Update(double price, double size, bool isBuy, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_trade_sign_autocorrelation_update(_handle.DangerousGetHandle(), price, size, isBuy, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_trade_sign_autocorrelation_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_trade_sign_autocorrelation_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_trade_sign_autocorrelation_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_trade_sign_autocorrelation_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TradeVolumeIndex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TradeVolumeIndex(double minTick)
|
|
{
|
|
var ptr = NativeMethods.wickra_trade_volume_index_new(minTick);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TradeVolumeIndex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_trade_volume_index_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_trade_volume_index_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_trade_volume_index_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_trade_volume_index_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_trade_volume_index_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_trade_volume_index_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_trade_volume_index_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TrendLabel : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TrendLabel(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_trend_label_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TrendLabel parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_trend_label_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_trend_label_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_trend_label_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_trend_label_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_trend_label_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_trend_label_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_trend_label_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TrendStrengthIndex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TrendStrengthIndex(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_trend_strength_index_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TrendStrengthIndex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_trend_strength_index_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_trend_strength_index_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_trend_strength_index_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_trend_strength_index_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_trend_strength_index_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_trend_strength_index_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_trend_strength_index_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Trendflex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Trendflex(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_trendflex_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Trendflex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_trendflex_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_trendflex_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_trendflex_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_trendflex_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_trendflex_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_trendflex_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_trendflex_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TreynorRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TreynorRatio(int period, double riskFree)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_treynor_ratio_new((nuint)period, riskFree);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TreynorRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_treynor_ratio_free);
|
|
}
|
|
|
|
public double Update(double x, double y)
|
|
{
|
|
var result = NativeMethods.wickra_treynor_ratio_update(_handle.DangerousGetHandle(), x, y);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> x, ReadOnlySpan<double> y)
|
|
{
|
|
var n = x.Length;
|
|
if (y.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* xPtr = x)
|
|
fixed (double* yPtr = y)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_treynor_ratio_batch(_handle.DangerousGetHandle(), xPtr, yPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_treynor_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_treynor_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_treynor_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_treynor_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Triangle : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Triangle()
|
|
{
|
|
var ptr = NativeMethods.wickra_triangle_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Triangle parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_triangle_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_triangle_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_triangle_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_triangle_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_triangle_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_triangle_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_triangle_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Trima : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Trima(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_trima_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Trima parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_trima_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_trima_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_trima_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_trima_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_trima_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_trima_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_trima_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Trin : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Trin()
|
|
{
|
|
var ptr = NativeMethods.wickra_trin_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Trin parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_trin_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> change, ReadOnlySpan<double> volume, ReadOnlySpan<bool> newHigh, ReadOnlySpan<bool> newLow, ReadOnlySpan<bool> aboveMa, ReadOnlySpan<bool> onBuySignal, long timestamp)
|
|
{
|
|
if (volume.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newHigh.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newLow.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (aboveMa.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (onBuySignal.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* changePtr = change)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (bool* newHighPtr = newHigh)
|
|
fixed (bool* newLowPtr = newLow)
|
|
fixed (bool* aboveMaPtr = aboveMa)
|
|
fixed (bool* onBuySignalPtr = onBuySignal)
|
|
{
|
|
result = NativeMethods.wickra_trin_update(_handle.DangerousGetHandle(), changePtr, volumePtr, newHighPtr, newLowPtr, aboveMaPtr, onBuySignalPtr, (nuint)change.Length, timestamp);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_trin_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_trin_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_trin_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_trin_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TripleTopBottom : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TripleTopBottom()
|
|
{
|
|
var ptr = NativeMethods.wickra_triple_top_bottom_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TripleTopBottom parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_triple_top_bottom_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_triple_top_bottom_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_triple_top_bottom_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_triple_top_bottom_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_triple_top_bottom_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_triple_top_bottom_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_triple_top_bottom_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Tristar : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Tristar()
|
|
{
|
|
var ptr = NativeMethods.wickra_tristar_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Tristar parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_tristar_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_tristar_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_tristar_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_tristar_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_tristar_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_tristar_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_tristar_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Trix : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Trix(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_trix_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Trix parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_trix_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_trix_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_trix_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_trix_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_trix_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_trix_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_trix_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TrueRange : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TrueRange()
|
|
{
|
|
var ptr = NativeMethods.wickra_true_range_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TrueRange parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_true_range_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_true_range_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_true_range_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_true_range_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_true_range_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_true_range_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_true_range_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Tsf : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Tsf(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_tsf_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Tsf parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_tsf_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_tsf_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_tsf_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_tsf_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_tsf_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_tsf_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_tsf_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TsfOscillator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TsfOscillator(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_tsf_oscillator_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TsfOscillator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_tsf_oscillator_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_tsf_oscillator_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_tsf_oscillator_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_tsf_oscillator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_tsf_oscillator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_tsf_oscillator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_tsf_oscillator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Tsi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Tsi(int @long, int @short)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(@long);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(@short);
|
|
var ptr = NativeMethods.wickra_tsi_new((nuint)@long, (nuint)@short);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Tsi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_tsi_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_tsi_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_tsi_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_tsi_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_tsi_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_tsi_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_tsi_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Tsv : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Tsv(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_tsv_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Tsv parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_tsv_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_tsv_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_tsv_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_tsv_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_tsv_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_tsv_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_tsv_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TtmSqueeze : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TtmSqueeze(int period, double bbMult, double kcMult)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_ttm_squeeze_new((nuint)period, bbMult, kcMult);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TtmSqueeze parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ttm_squeeze_free);
|
|
}
|
|
|
|
public TtmSqueezeOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraTtmSqueezeOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_ttm_squeeze_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new TtmSqueezeOutput(native.squeeze, native.momentum) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ttm_squeeze_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ttm_squeeze_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ttm_squeeze_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ttm_squeeze_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TtmTrend : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TtmTrend(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_ttm_trend_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TtmTrend parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ttm_trend_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_ttm_trend_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_ttm_trend_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ttm_trend_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ttm_trend_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ttm_trend_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ttm_trend_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TurnOfMonth : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TurnOfMonth(uint nFirst, uint nLast, int utcOffsetMinutes)
|
|
{
|
|
var ptr = NativeMethods.wickra_turn_of_month_new(nFirst, nLast, utcOffsetMinutes);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TurnOfMonth parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_turn_of_month_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_turn_of_month_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_turn_of_month_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_turn_of_month_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_turn_of_month_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_turn_of_month_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_turn_of_month_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Tweezer : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Tweezer()
|
|
{
|
|
var ptr = NativeMethods.wickra_tweezer_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Tweezer parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_tweezer_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_tweezer_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_tweezer_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_tweezer_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_tweezer_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_tweezer_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_tweezer_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TwiggsMoneyFlow : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TwiggsMoneyFlow(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_twiggs_money_flow_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TwiggsMoneyFlow parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_twiggs_money_flow_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_twiggs_money_flow_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_twiggs_money_flow_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_twiggs_money_flow_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_twiggs_money_flow_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_twiggs_money_flow_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_twiggs_money_flow_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TwoCrows : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TwoCrows()
|
|
{
|
|
var ptr = NativeMethods.wickra_two_crows_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TwoCrows parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_two_crows_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_two_crows_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_two_crows_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_two_crows_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_two_crows_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_two_crows_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_two_crows_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class TypicalPrice : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public TypicalPrice()
|
|
{
|
|
var ptr = NativeMethods.wickra_typical_price_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid TypicalPrice parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_typical_price_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_typical_price_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_typical_price_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_typical_price_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_typical_price_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_typical_price_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_typical_price_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class UlcerIndex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public UlcerIndex(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_ulcer_index_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid UlcerIndex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ulcer_index_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_ulcer_index_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_ulcer_index_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ulcer_index_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ulcer_index_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ulcer_index_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ulcer_index_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class UltimateOscillator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public UltimateOscillator(int @short, int mid, int @long)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(@short);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(mid);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(@long);
|
|
var ptr = NativeMethods.wickra_ultimate_oscillator_new((nuint)@short, (nuint)mid, (nuint)@long);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid UltimateOscillator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_ultimate_oscillator_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_ultimate_oscillator_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_ultimate_oscillator_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_ultimate_oscillator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_ultimate_oscillator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_ultimate_oscillator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_ultimate_oscillator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class UniqueThreeRiver : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public UniqueThreeRiver()
|
|
{
|
|
var ptr = NativeMethods.wickra_unique_three_river_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid UniqueThreeRiver parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_unique_three_river_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_unique_three_river_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_unique_three_river_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_unique_three_river_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_unique_three_river_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_unique_three_river_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_unique_three_river_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class UniversalOscillator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public UniversalOscillator(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_universal_oscillator_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid UniversalOscillator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_universal_oscillator_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_universal_oscillator_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_universal_oscillator_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_universal_oscillator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_universal_oscillator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_universal_oscillator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_universal_oscillator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class UpDownVolumeRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public UpDownVolumeRatio()
|
|
{
|
|
var ptr = NativeMethods.wickra_up_down_volume_ratio_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid UpDownVolumeRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_up_down_volume_ratio_free);
|
|
}
|
|
|
|
public double Update(ReadOnlySpan<double> change, ReadOnlySpan<double> volume, ReadOnlySpan<bool> newHigh, ReadOnlySpan<bool> newLow, ReadOnlySpan<bool> aboveMa, ReadOnlySpan<bool> onBuySignal, long timestamp)
|
|
{
|
|
if (volume.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newHigh.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (newLow.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (aboveMa.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
if (onBuySignal.Length != change.Length)
|
|
{
|
|
throw new ArgumentException("input spans in the same group must have equal length");
|
|
}
|
|
|
|
double result;
|
|
unsafe
|
|
{
|
|
fixed (double* changePtr = change)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (bool* newHighPtr = newHigh)
|
|
fixed (bool* newLowPtr = newLow)
|
|
fixed (bool* aboveMaPtr = aboveMa)
|
|
fixed (bool* onBuySignalPtr = onBuySignal)
|
|
{
|
|
result = NativeMethods.wickra_up_down_volume_ratio_update(_handle.DangerousGetHandle(), changePtr, volumePtr, newHighPtr, newLowPtr, aboveMaPtr, onBuySignalPtr, (nuint)change.Length, timestamp);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_up_down_volume_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_up_down_volume_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_up_down_volume_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_up_down_volume_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class UpsideGapThreeMethods : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public UpsideGapThreeMethods()
|
|
{
|
|
var ptr = NativeMethods.wickra_upside_gap_three_methods_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid UpsideGapThreeMethods parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_upside_gap_three_methods_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_upside_gap_three_methods_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_upside_gap_three_methods_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_upside_gap_three_methods_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_upside_gap_three_methods_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_upside_gap_three_methods_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_upside_gap_three_methods_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class UpsideGapTwoCrows : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public UpsideGapTwoCrows()
|
|
{
|
|
var ptr = NativeMethods.wickra_upside_gap_two_crows_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid UpsideGapTwoCrows parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_upside_gap_two_crows_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_upside_gap_two_crows_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_upside_gap_two_crows_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_upside_gap_two_crows_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_upside_gap_two_crows_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_upside_gap_two_crows_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_upside_gap_two_crows_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class UpsidePotentialRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public UpsidePotentialRatio(int period, double mar)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_upside_potential_ratio_new((nuint)period, mar);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid UpsidePotentialRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_upside_potential_ratio_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_upside_potential_ratio_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_upside_potential_ratio_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_upside_potential_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_upside_potential_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_upside_potential_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_upside_potential_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ValueArea : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ValueArea(int period, int binCount, double valueAreaPct)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(binCount);
|
|
var ptr = NativeMethods.wickra_value_area_new((nuint)period, (nuint)binCount, valueAreaPct);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ValueArea parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_value_area_free);
|
|
}
|
|
|
|
public ValueAreaOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraValueAreaOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_value_area_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new ValueAreaOutput(native.poc, native.vah, native.val) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_value_area_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_value_area_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_value_area_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_value_area_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ValueAtRisk : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ValueAtRisk(int period, double confidence)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_value_at_risk_new((nuint)period, confidence);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ValueAtRisk parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_value_at_risk_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_value_at_risk_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_value_at_risk_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_value_at_risk_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_value_at_risk_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_value_at_risk_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_value_at_risk_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Variance : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Variance(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_variance_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Variance parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_variance_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_variance_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_variance_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_variance_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_variance_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_variance_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_variance_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class VarianceRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public VarianceRatio(int period, int q)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(q);
|
|
var ptr = NativeMethods.wickra_variance_ratio_new((nuint)period, (nuint)q);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid VarianceRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_variance_ratio_free);
|
|
}
|
|
|
|
public double Update(double x, double y)
|
|
{
|
|
var result = NativeMethods.wickra_variance_ratio_update(_handle.DangerousGetHandle(), x, y);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> x, ReadOnlySpan<double> y)
|
|
{
|
|
var n = x.Length;
|
|
if (y.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* xPtr = x)
|
|
fixed (double* yPtr = y)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_variance_ratio_batch(_handle.DangerousGetHandle(), xPtr, yPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_variance_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_variance_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_variance_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_variance_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class VerticalHorizontalFilter : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public VerticalHorizontalFilter(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_vertical_horizontal_filter_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid VerticalHorizontalFilter parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_vertical_horizontal_filter_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_vertical_horizontal_filter_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_vertical_horizontal_filter_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_vertical_horizontal_filter_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_vertical_horizontal_filter_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_vertical_horizontal_filter_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_vertical_horizontal_filter_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Vidya : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Vidya(int period, int cmoPeriod)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(cmoPeriod);
|
|
var ptr = NativeMethods.wickra_vidya_new((nuint)period, (nuint)cmoPeriod);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Vidya parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_vidya_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_vidya_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_vidya_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_vidya_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_vidya_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_vidya_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_vidya_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class VolatilityCone : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public VolatilityCone(int window, int lookback)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(window);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(lookback);
|
|
var ptr = NativeMethods.wickra_volatility_cone_new((nuint)window, (nuint)lookback);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid VolatilityCone parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_volatility_cone_free);
|
|
}
|
|
|
|
public VolatilityConeOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraVolatilityConeOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_volatility_cone_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new VolatilityConeOutput(native.current, native.min, native.median, native.max, native.percentile) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_volatility_cone_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_volatility_cone_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_volatility_cone_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_volatility_cone_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class VolatilityOfVolatility : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public VolatilityOfVolatility(int volWindow, int vovWindow)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(volWindow);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(vovWindow);
|
|
var ptr = NativeMethods.wickra_volatility_of_volatility_new((nuint)volWindow, (nuint)vovWindow);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid VolatilityOfVolatility parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_volatility_of_volatility_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_volatility_of_volatility_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_volatility_of_volatility_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_volatility_of_volatility_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_volatility_of_volatility_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_volatility_of_volatility_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_volatility_of_volatility_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class VolatilityRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public VolatilityRatio(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_volatility_ratio_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid VolatilityRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_volatility_ratio_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_volatility_ratio_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_volatility_ratio_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_volatility_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_volatility_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_volatility_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_volatility_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class VoltyStop : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public VoltyStop(int atrPeriod, double multiplier)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(atrPeriod);
|
|
var ptr = NativeMethods.wickra_volty_stop_new((nuint)atrPeriod, multiplier);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid VoltyStop parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_volty_stop_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_volty_stop_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_volty_stop_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_volty_stop_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_volty_stop_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_volty_stop_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_volty_stop_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class VolumeBars : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public VolumeBars(double volumePerBar)
|
|
{
|
|
var ptr = NativeMethods.wickra_volume_bars_new(volumePerBar);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid VolumeBars parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_volume_bars_free);
|
|
}
|
|
|
|
public VolumeBar[] Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
const int cap = 64;
|
|
Span<WickraVolumeBar> buffer = stackalloc WickraVolumeBar[cap];
|
|
long count;
|
|
unsafe
|
|
{
|
|
fixed (WickraVolumeBar* ptr = buffer)
|
|
{
|
|
count = (long)NativeMethods.wickra_volume_bars_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, ptr, (nuint)cap);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
if (count <= 0)
|
|
{
|
|
return Array.Empty<VolumeBar>();
|
|
}
|
|
|
|
var result = new VolumeBar[count];
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
result[i] = new VolumeBar(buffer[i].open, buffer[i].high, buffer[i].low, buffer[i].close, buffer[i].volume);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_volume_bars_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_volume_bars_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class VolumeByTimeProfile : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
private readonly int _valuesCapacity;
|
|
|
|
public VolumeByTimeProfile(int buckets, int utcOffsetMinutes)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(buckets);
|
|
var ptr = NativeMethods.wickra_volume_by_time_profile_new((nuint)buckets, utcOffsetMinutes);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid VolumeByTimeProfile parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_volume_by_time_profile_free);
|
|
_valuesCapacity = buckets;
|
|
}
|
|
|
|
public double[]? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var values = new double[_valuesCapacity];
|
|
long length;
|
|
unsafe
|
|
{
|
|
fixed (double* valuesPtr = values)
|
|
{
|
|
length = (long)NativeMethods.wickra_volume_by_time_profile_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, valuesPtr, (nuint)_valuesCapacity);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
if (length < 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (length < values.Length)
|
|
{
|
|
Array.Resize(ref values, (int)length);
|
|
}
|
|
|
|
return values;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_volume_by_time_profile_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_volume_by_time_profile_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_volume_by_time_profile_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_volume_by_time_profile_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class VolumeOscillator : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public VolumeOscillator(int fast, int slow)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(fast);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(slow);
|
|
var ptr = NativeMethods.wickra_volume_oscillator_new((nuint)fast, (nuint)slow);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid VolumeOscillator parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_volume_oscillator_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_volume_oscillator_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_volume_oscillator_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_volume_oscillator_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_volume_oscillator_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_volume_oscillator_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_volume_oscillator_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class VolumePriceTrend : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public VolumePriceTrend()
|
|
{
|
|
var ptr = NativeMethods.wickra_volume_price_trend_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid VolumePriceTrend parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_volume_price_trend_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_volume_price_trend_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_volume_price_trend_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_volume_price_trend_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_volume_price_trend_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_volume_price_trend_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_volume_price_trend_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class VolumeProfile : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
private readonly int _valuesCapacity;
|
|
|
|
public VolumeProfile(int period, int binCount)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(binCount);
|
|
var ptr = NativeMethods.wickra_volume_profile_new((nuint)period, (nuint)binCount);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid VolumeProfile parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_volume_profile_free);
|
|
_valuesCapacity = binCount;
|
|
}
|
|
|
|
public VolumeProfileOutputScalars? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var values = new double[_valuesCapacity];
|
|
WickraVolumeProfileOutputScalars scalars;
|
|
long length;
|
|
unsafe
|
|
{
|
|
fixed (double* valuesPtr = values)
|
|
{
|
|
length = (long)NativeMethods.wickra_volume_profile_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &scalars, valuesPtr, (nuint)_valuesCapacity);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
if (length < 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (length < values.Length)
|
|
{
|
|
Array.Resize(ref values, (int)length);
|
|
}
|
|
|
|
return new VolumeProfileOutputScalars(scalars.price_low, scalars.price_high, values);
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_volume_profile_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_volume_profile_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_volume_profile_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_volume_profile_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class VolumeRsi : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public VolumeRsi(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_volume_rsi_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid VolumeRsi parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_volume_rsi_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_volume_rsi_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_volume_rsi_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_volume_rsi_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_volume_rsi_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_volume_rsi_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_volume_rsi_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class VolumeWeightedMacd : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public VolumeWeightedMacd(int fast, int slow, int signal)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(fast);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(slow);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(signal);
|
|
var ptr = NativeMethods.wickra_volume_weighted_macd_new((nuint)fast, (nuint)slow, (nuint)signal);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid VolumeWeightedMacd parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_volume_weighted_macd_free);
|
|
}
|
|
|
|
public VolumeWeightedMacdOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraVolumeWeightedMacdOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_volume_weighted_macd_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new VolumeWeightedMacdOutput(native.macd, native.signal, native.histogram) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_volume_weighted_macd_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_volume_weighted_macd_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_volume_weighted_macd_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_volume_weighted_macd_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class VolumeWeightedSr : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public VolumeWeightedSr(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_volume_weighted_sr_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid VolumeWeightedSr parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_volume_weighted_sr_free);
|
|
}
|
|
|
|
public VolumeWeightedSrOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraVolumeWeightedSrOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_volume_weighted_sr_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new VolumeWeightedSrOutput(native.support, native.resistance) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_volume_weighted_sr_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_volume_weighted_sr_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_volume_weighted_sr_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_volume_weighted_sr_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Vortex : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Vortex(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_vortex_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Vortex parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_vortex_free);
|
|
}
|
|
|
|
public VortexOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraVortexOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_vortex_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new VortexOutput(native.plus, native.minus) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_vortex_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_vortex_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_vortex_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_vortex_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Vpin : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Vpin(double bucketVolume, int numBuckets)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(numBuckets);
|
|
var ptr = NativeMethods.wickra_vpin_new(bucketVolume, (nuint)numBuckets);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Vpin parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_vpin_free);
|
|
}
|
|
|
|
public double Update(double price, double size, bool isBuy, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_vpin_update(_handle.DangerousGetHandle(), price, size, isBuy, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_vpin_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_vpin_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_vpin_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_vpin_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Vwap : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Vwap()
|
|
{
|
|
var ptr = NativeMethods.wickra_vwap_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Vwap parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_vwap_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_vwap_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_vwap_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_vwap_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_vwap_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_vwap_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_vwap_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class VwapStdDevBands : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public VwapStdDevBands(double multiplier)
|
|
{
|
|
var ptr = NativeMethods.wickra_vwap_std_dev_bands_new(multiplier);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid VwapStdDevBands parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_vwap_std_dev_bands_free);
|
|
}
|
|
|
|
public VwapStdDevBandsOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraVwapStdDevBandsOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_vwap_std_dev_bands_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new VwapStdDevBandsOutput(native.upper, native.middle, native.lower, native.stddev) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_vwap_std_dev_bands_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_vwap_std_dev_bands_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_vwap_std_dev_bands_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_vwap_std_dev_bands_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Vwma : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Vwma(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_vwma_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Vwma parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_vwma_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_vwma_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_vwma_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_vwma_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_vwma_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_vwma_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_vwma_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Vzo : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Vzo(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_vzo_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Vzo parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_vzo_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_vzo_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_vzo_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_vzo_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_vzo_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_vzo_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_vzo_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Wad : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Wad()
|
|
{
|
|
var ptr = NativeMethods.wickra_wad_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Wad parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_wad_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_wad_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_wad_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_wad_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_wad_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_wad_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_wad_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class WavePm : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public WavePm(int length, int smoothing)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(length);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(smoothing);
|
|
var ptr = NativeMethods.wickra_wave_pm_new((nuint)length, (nuint)smoothing);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid WavePm parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_wave_pm_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_wave_pm_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_wave_pm_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_wave_pm_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_wave_pm_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_wave_pm_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_wave_pm_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class WaveTrend : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public WaveTrend(int channelPeriod, int averagePeriod, int signalPeriod)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(channelPeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(averagePeriod);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(signalPeriod);
|
|
var ptr = NativeMethods.wickra_wave_trend_new((nuint)channelPeriod, (nuint)averagePeriod, (nuint)signalPeriod);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid WaveTrend parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_wave_trend_free);
|
|
}
|
|
|
|
public WaveTrendOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraWaveTrendOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_wave_trend_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new WaveTrendOutput(native.wt1, native.wt2) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_wave_trend_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_wave_trend_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_wave_trend_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_wave_trend_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Wedge : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Wedge()
|
|
{
|
|
var ptr = NativeMethods.wickra_wedge_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Wedge parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_wedge_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_wedge_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_wedge_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_wedge_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_wedge_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_wedge_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_wedge_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class WeightedClose : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public WeightedClose()
|
|
{
|
|
var ptr = NativeMethods.wickra_weighted_close_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid WeightedClose parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_weighted_close_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_weighted_close_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_weighted_close_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_weighted_close_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_weighted_close_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_weighted_close_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_weighted_close_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class WickRatio : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public WickRatio()
|
|
{
|
|
var ptr = NativeMethods.wickra_wick_ratio_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid WickRatio parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_wick_ratio_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_wick_ratio_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_wick_ratio_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_wick_ratio_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_wick_ratio_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_wick_ratio_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_wick_ratio_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class WilliamsFractals : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public WilliamsFractals()
|
|
{
|
|
var ptr = NativeMethods.wickra_williams_fractals_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid WilliamsFractals parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_williams_fractals_free);
|
|
}
|
|
|
|
public WilliamsFractalsOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraWilliamsFractalsOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_williams_fractals_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new WilliamsFractalsOutput(native.up, native.down) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_williams_fractals_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_williams_fractals_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_williams_fractals_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_williams_fractals_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class WilliamsR : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public WilliamsR(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_williams_r_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid WilliamsR parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_williams_r_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_williams_r_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_williams_r_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_williams_r_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_williams_r_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_williams_r_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_williams_r_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class WinRate : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public WinRate(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_win_rate_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid WinRate parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_win_rate_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_win_rate_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_win_rate_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_win_rate_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_win_rate_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_win_rate_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_win_rate_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Wma : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Wma(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_wma_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Wma parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_wma_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_wma_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_wma_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_wma_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_wma_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_wma_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_wma_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class WoodiePivots : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public WoodiePivots()
|
|
{
|
|
var ptr = NativeMethods.wickra_woodie_pivots_new();
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid WoodiePivots parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_woodie_pivots_free);
|
|
}
|
|
|
|
public WoodiePivotsOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraWoodiePivotsOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_woodie_pivots_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new WoodiePivotsOutput(native.pp, native.r1, native.r2, native.s1, native.s2) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_woodie_pivots_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_woodie_pivots_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_woodie_pivots_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_woodie_pivots_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class YangZhangVolatility : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public YangZhangVolatility(int period, int tradingPeriods)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(tradingPeriods);
|
|
var ptr = NativeMethods.wickra_yang_zhang_volatility_new((nuint)period, (nuint)tradingPeriods);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid YangZhangVolatility parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_yang_zhang_volatility_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_yang_zhang_volatility_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_yang_zhang_volatility_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_yang_zhang_volatility_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_yang_zhang_volatility_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_yang_zhang_volatility_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_yang_zhang_volatility_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class YoyoExit : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public YoyoExit(int atrPeriod, double multiplier)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(atrPeriod);
|
|
var ptr = NativeMethods.wickra_yoyo_exit_new((nuint)atrPeriod, multiplier);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid YoyoExit parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_yoyo_exit_free);
|
|
}
|
|
|
|
public double Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
var result = NativeMethods.wickra_yoyo_exit_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> open, ReadOnlySpan<double> high, ReadOnlySpan<double> low, ReadOnlySpan<double> close, ReadOnlySpan<double> volume, ReadOnlySpan<long> timestamp)
|
|
{
|
|
var n = open.Length;
|
|
if (high.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (low.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (close.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (volume.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
if (timestamp.Length != n)
|
|
{
|
|
throw new ArgumentException("all input spans must have the same length");
|
|
}
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* openPtr = open)
|
|
fixed (double* highPtr = high)
|
|
fixed (double* lowPtr = low)
|
|
fixed (double* closePtr = close)
|
|
fixed (double* volumePtr = volume)
|
|
fixed (long* timestampPtr = timestamp)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_yoyo_exit_batch(_handle.DangerousGetHandle(), openPtr, highPtr, lowPtr, closePtr, volumePtr, timestampPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_yoyo_exit_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_yoyo_exit_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_yoyo_exit_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_yoyo_exit_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ZScore : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ZScore(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_z_score_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ZScore parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_z_score_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_z_score_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_z_score_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_z_score_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_z_score_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_z_score_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_z_score_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ZeroLagMacd : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ZeroLagMacd(int fast, int slow, int signal)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(fast);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(slow);
|
|
ArgumentOutOfRangeException.ThrowIfNegative(signal);
|
|
var ptr = NativeMethods.wickra_zero_lag_macd_new((nuint)fast, (nuint)slow, (nuint)signal);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ZeroLagMacd parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_zero_lag_macd_free);
|
|
}
|
|
|
|
public ZeroLagMacdOutput? Update(double @value)
|
|
{
|
|
WickraZeroLagMacdOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_zero_lag_macd_update(_handle.DangerousGetHandle(), @value, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new ZeroLagMacdOutput(native.macd, native.signal, native.histogram) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_zero_lag_macd_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_zero_lag_macd_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_zero_lag_macd_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_zero_lag_macd_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class ZigZag : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public ZigZag(double threshold)
|
|
{
|
|
var ptr = NativeMethods.wickra_zig_zag_new(threshold);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid ZigZag parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_zig_zag_free);
|
|
}
|
|
|
|
public ZigZagOutput? Update(double open, double high, double low, double close, double volume, long timestamp)
|
|
{
|
|
WickraZigZagOutput native;
|
|
bool ok;
|
|
unsafe
|
|
{
|
|
ok = NativeMethods.wickra_zig_zag_update(_handle.DangerousGetHandle(), open, high, low, close, volume, timestamp, &native);
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return ok ? new ZigZagOutput(native.swing, native.direction) : null;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_zig_zag_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_zig_zag_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_zig_zag_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_zig_zag_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|
|
public sealed class Zlema : IDisposable
|
|
{
|
|
private readonly WickraHandle _handle;
|
|
|
|
public Zlema(int period)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegative(period);
|
|
var ptr = NativeMethods.wickra_zlema_new((nuint)period);
|
|
if (ptr == nint.Zero)
|
|
{
|
|
throw new ArgumentException("invalid Zlema parameters");
|
|
}
|
|
|
|
_handle = new WickraHandle(ptr, NativeMethods.wickra_zlema_free);
|
|
}
|
|
|
|
public double Update(double @value)
|
|
{
|
|
var result = NativeMethods.wickra_zlema_update(_handle.DangerousGetHandle(), @value);
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
public double[] Batch(ReadOnlySpan<double> input)
|
|
{
|
|
var n = input.Length;
|
|
|
|
var output = new double[n];
|
|
unsafe
|
|
{
|
|
fixed (double* inputPtr = input)
|
|
fixed (double* outputPtr = output)
|
|
{
|
|
NativeMethods.wickra_zlema_batch(_handle.DangerousGetHandle(), inputPtr, outputPtr, (nuint)n);
|
|
}
|
|
}
|
|
|
|
GC.KeepAlive(_handle);
|
|
return output;
|
|
}
|
|
|
|
/// <summary>Number of updates required before <see cref="Update"/> yields a value.</summary>
|
|
public int WarmupPeriod()
|
|
{
|
|
var result = (int)NativeMethods.wickra_zlema_warmup_period(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>Whether the indicator has consumed enough input to emit a value.</summary>
|
|
public bool IsReady()
|
|
{
|
|
var result = NativeMethods.wickra_zlema_is_ready(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>The indicator's canonical name.</summary>
|
|
public string Name()
|
|
{
|
|
var ptr = NativeMethods.wickra_zlema_name(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr) ?? string.Empty;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NativeMethods.wickra_zlema_reset(_handle.DangerousGetHandle());
|
|
GC.KeepAlive(_handle);
|
|
}
|
|
|
|
public void Dispose() => _handle.Dispose();
|
|
}
|
|
|