fd9f4c8bc6
* feat(bindings): expose name() on every indicator in Node, WASM, and Python Surface the core Indicator::name() / BarBuilder::name() accessor through the three native bindings so every indicator reports its canonical name at runtime, matching the existing reset/isReady/warmupPeriod surface. - Node (napi): name(): string on all 514 classes (regenerated index.d.ts) - WASM (wasm-bindgen): name(): string on all 514 classes - Python (pyo3): name() -> str on all classes * feat(bindings): expose name() across the C ABI and C/C++/Go/C#/Java/R Regenerate the C ABI and the four generated language bindings from the updated ScriptHelpers generators so every indicator and bar builder reports its canonical name at runtime, completing name() coverage across all 10 languages. - C ABI (bindings/c): wickra_<ind>_name() -> *const c_char for all 514, cached in a per-function OnceLock<CString> with ind.name() as the source of truth; cbindgen header regenerated and vendored into bindings/go/include. - Go: Name() string; C#: string Name(); Java: String name(); R: name() S3 generic over the wk_<ind>_name C glue (methods.R + NAMESPACE). The Java regeneration also restores two fixes that had drifted out of the generator (bool* arrays via boolSegment; uint8_t ctor args cast to byte) and C# re-emits '#nullable enable'; these are no-op vs the previous committed output apart from the new name() accessors. * test(golden): pin canonical name() across all 10 language bindings Add a cross-language name() consistency check: every indicator must report the exact core Indicator::name() (which can differ from the registered class name, e.g. ChaikinMoneyFlow -> "CMF", Donchian -> "DonchianChannels"). The 514 core names are committed as testdata/golden/names.json (keyed by Rust canonical) and asserted by each binding's golden replay, which already reconstructs the whole catalogue: - node / wasm: assert against names.json in the existing golden test - python: new test_golden_names.py over the shared node manifest - go / csharp / java / c+c++ / r: the golden-test generators load names.json and emit a name assertion per indicator (regenerated test artifacts committed) All 10 bindings return identical names by construction (each delegates to core), so this pins that contract and guards against a future binding breaking the passthrough. * docs(changelog): record name() across all 10 bindings under Unreleased * fix(r): restore bool* flag marshalling in the regenerated C glue The name() regeneration had reverted the cross-section bool fix: the R glue emitted (bool *)REAL(x) for const bool* inputs, reinterpreting 8-byte doubles as 1-byte bools so every flag read as false (PercentAboveMa, NewHighsNewLows, HighLowIndex, BullishPercentIndex returned 0 instead of the breadth value). The wk_bool_vec() helper is restored in the generator and the glue routes bool arrays through it again.
41367 lines
1.3 MiB
Plaintext
41367 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 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 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 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 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();
|
|
}
|
|
|